Annotation of researchv10dc/cmd/gcc/explow.c, revision 1.1

1.1     ! root        1: /* Subroutines for manipulating rtx's in semantically interesting ways.
        !             2:    Copyright (C) 1987 Free Software Foundation, Inc.
        !             3: 
        !             4: This file is part of GNU CC.
        !             5: 
        !             6: GNU CC is distributed in the hope that it will be useful,
        !             7: but WITHOUT ANY WARRANTY.  No author or distributor
        !             8: accepts responsibility to anyone for the consequences of using it
        !             9: or for whether it serves any particular purpose or works at all,
        !            10: unless he says so in writing.  Refer to the GNU CC General Public
        !            11: License for full details.
        !            12: 
        !            13: Everyone is granted permission to copy, modify and redistribute
        !            14: GNU CC, but only under the conditions described in the
        !            15: GNU CC General Public License.   A copy of this license is
        !            16: supposed to have been given to you along with GNU CC so you
        !            17: can know your rights and responsibilities.  It should be in a
        !            18: file named COPYING.  Among other things, the copyright notice
        !            19: and this notice must be preserved on all copies.  */
        !            20: 
        !            21: 
        !            22: #include "config.h"
        !            23: #include "rtl.h"
        !            24: #include "tree.h"
        !            25: #include "flags.h"
        !            26: #include "expr.h"
        !            27: 
        !            28: /* Return an rtx for the sum of X and the integer C.  */
        !            29: 
        !            30: rtx
        !            31: plus_constant (x, c)
        !            32:      register rtx x;
        !            33:      register int c;
        !            34: {
        !            35:   register RTX_CODE code = GET_CODE (x);
        !            36:   register enum machine_mode mode = GET_MODE (x);
        !            37:   int all_constant = 0;
        !            38: 
        !            39:   if (c == 0)
        !            40:     return x;
        !            41: 
        !            42:   if (code == CONST_INT)
        !            43:     return gen_rtx (CONST_INT, VOIDmode, (INTVAL (x) + c));
        !            44: 
        !            45:   /* If adding to something entirely constant, set a flag
        !            46:      so that we can add a CONST around the result.  */
        !            47:   if (code == CONST)
        !            48:     {
        !            49:       x = XEXP (x, 0);
        !            50:       all_constant = 1;
        !            51:     }
        !            52:   else if (code == SYMBOL_REF || code == LABEL_REF)
        !            53:     all_constant = 1;
        !            54: 
        !            55:   /* The interesting case is adding the integer to a sum.
        !            56:      Look for constant term in the sum and combine
        !            57:      with C.  For an integer constant term, we make a combined
        !            58:      integer.  For a constant term that is not an explicit integer,
        !            59:      we cannot really combine, but group them together anyway.  */
        !            60: 
        !            61:   if (GET_CODE (x) == PLUS)
        !            62:     {
        !            63:       if (GET_CODE (XEXP (x, 0)) == CONST_INT)
        !            64:        {
        !            65:          c += INTVAL (XEXP (x, 0));
        !            66:          x = XEXP (x, 1);
        !            67:        }
        !            68:       else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
        !            69:        {
        !            70:          c += INTVAL (XEXP (x, 1));
        !            71:          x = XEXP (x, 0);
        !            72:        }
        !            73:       else if (CONSTANT_P (XEXP (x, 0)))
        !            74:        {
        !            75:          return gen_rtx (PLUS, mode,
        !            76:                          plus_constant (XEXP (x, 0), c),
        !            77:                          XEXP (x, 1));
        !            78:        }
        !            79:       else if (CONSTANT_P (XEXP (x, 1)))
        !            80:        {
        !            81:          return gen_rtx (PLUS, mode,
        !            82:                          XEXP (x, 0),
        !            83:                          plus_constant (XEXP (x, 1), c));
        !            84:        }
        !            85: #ifdef OLD_INDEXING
        !            86:       /* Detect adding a constant to an indexed address
        !            87:         of the form (PLUS (MULT (REG) (CONST)) regs-and-constants).
        !            88:         Keep the (MULT ...) at the top level of addition so that
        !            89:         the result is still suitable for indexing and constants
        !            90:         are combined.  */
        !            91:       else if (GET_CODE (XEXP (x, 0)) == MULT)
        !            92:        {
        !            93:          return gen_rtx (PLUS, mode, XEXP (x, 0),
        !            94:                          plus_constant (XEXP (x, 1), c));
        !            95:        }
        !            96:       else if (GET_CODE (XEXP (x, 1)) == MULT)
        !            97:        {
        !            98:          return gen_rtx (PLUS, mode, plus_constant (XEXP (x, 0), c),
        !            99:                          XEXP (x, 1));
        !           100:        }
        !           101: #endif
        !           102:     }
        !           103:   if (c != 0)
        !           104:     x = gen_rtx (PLUS, mode, x, gen_rtx (CONST_INT, VOIDmode, c));
        !           105: 
        !           106:   if (all_constant)
        !           107:     return gen_rtx (CONST, mode, x);
        !           108:   else
        !           109:     return x;
        !           110: }
        !           111: 
        !           112: /* If X is a sum, return a new sum like X but lacking any constant terms.
        !           113:    Add all the removed constant terms into *CONSTPTR.
        !           114:    X itself is not altered.  The result != X if and only if
        !           115:    it is not isomorphic to X.  */
        !           116: 
        !           117: rtx
        !           118: eliminate_constant_term (x, constptr)
        !           119:      rtx x;
        !           120:      int *constptr;
        !           121: {
        !           122:   int c;
        !           123:   register rtx x0, x1;
        !           124: 
        !           125:   if (GET_CODE (x) != PLUS)
        !           126:     return x;
        !           127: 
        !           128:   /* First handle constants appearing at this level explicitly.  */
        !           129:   if (GET_CODE (XEXP (x, 0)) == CONST_INT)
        !           130:     {
        !           131:       *constptr += INTVAL (XEXP (x, 0));
        !           132:       return eliminate_constant_term (XEXP (x, 1), constptr);
        !           133:     }
        !           134: 
        !           135:   if (GET_CODE (XEXP (x, 1)) == CONST_INT)
        !           136:     {
        !           137:       *constptr += INTVAL (XEXP (x, 1));
        !           138:       return eliminate_constant_term (XEXP (x, 0), constptr);
        !           139:     }
        !           140: 
        !           141:   c = 0;
        !           142:   x0 = eliminate_constant_term (XEXP (x, 0), &c);
        !           143:   x1 = eliminate_constant_term (XEXP (x, 1), &c);
        !           144:   if (x1 != XEXP (x, 1) || x0 != XEXP (x, 0))
        !           145:     {
        !           146:       *constptr += c;
        !           147:       return gen_rtx (PLUS, GET_MODE (x), x0, x1);
        !           148:     }
        !           149:   return x;
        !           150: }
        !           151: 
        !           152: /* Return an rtx for the size in bytes of the value of EXP.  */
        !           153: 
        !           154: rtx
        !           155: expr_size (exp)
        !           156:      tree exp;
        !           157: {
        !           158:   return expand_expr (size_in_bytes (TREE_TYPE (exp)), 0, SImode, 0);
        !           159: }
        !           160: 
        !           161: /* Not yet really written since C does not need it.  */
        !           162: 
        !           163: rtx
        !           164: lookup_static_chain ()
        !           165: {
        !           166:   abort ();
        !           167: }
        !           168: 
        !           169: /* Return a copy of X in which all memory references
        !           170:    and all constants that involve symbol refs
        !           171:    have been replaced with new temporary registers.
        !           172:    Also emit code to load the memory locations and constants
        !           173:    into those registers.
        !           174: 
        !           175:    If X contains no such constants or memory references,
        !           176:    X itself (not a copy) is returned.
        !           177: 
        !           178:    X may contain no arithmetic except addition, subtraction and multiplication.
        !           179:    Values returned by expand_expr with 1 for sum_ok fit this constraint.  */
        !           180: 
        !           181: static rtx
        !           182: break_out_memory_refs (x)
        !           183:      register rtx x;
        !           184: {
        !           185:   if (GET_CODE (x) == MEM || GET_CODE (x) == CONST
        !           186:       || GET_CODE (x) == SYMBOL_REF)
        !           187:     {
        !           188:       register rtx temp = force_reg (Pmode, x);
        !           189:       mark_reg_pointer (temp);
        !           190:       x = temp;
        !           191:     }
        !           192:   else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
        !           193:           || GET_CODE (x) == MULT)
        !           194:     {
        !           195:       register rtx op0 = break_out_memory_refs (XEXP (x, 0));
        !           196:       register rtx op1 = break_out_memory_refs (XEXP (x, 1));
        !           197:       if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
        !           198:        x = gen_rtx (GET_CODE (x), Pmode, op0, op1);
        !           199:     }
        !           200:   return x;
        !           201: }
        !           202: 
        !           203: /* Given a memory address or facsimile X, construct a new address,
        !           204:    currently equivalent, that is stable: future stores won't change it.
        !           205: 
        !           206:    X must be composed of constants, register and memory references
        !           207:    combined with addition, subtraction and multiplication:
        !           208:    in other words, just what you can get from expand_expr if sum_ok is 1.
        !           209: 
        !           210:    Works by making copies of all regs and memory locations used
        !           211:    by X and combining them the same way X does.
        !           212:    You could also stabilize the reference to this address
        !           213:    by copying the address to a register with copy_to_reg;
        !           214:    but then you wouldn't get indexed addressing in the reference.  */
        !           215: 
        !           216: rtx
        !           217: copy_all_regs (x)
        !           218:      register rtx x;
        !           219: {
        !           220:   if (GET_CODE (x) == REG)
        !           221:     {
        !           222:       if (REGNO (x) != FRAME_POINTER_REGNUM)
        !           223:        x = copy_to_reg (x);
        !           224:     }
        !           225:   else if (GET_CODE (x) == MEM)
        !           226:     x = copy_to_reg (x);
        !           227:   else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
        !           228:           || GET_CODE (x) == MULT)
        !           229:     {
        !           230:       register rtx op0 = copy_all_regs (XEXP (x, 0));
        !           231:       register rtx op1 = copy_all_regs (XEXP (x, 1));
        !           232:       if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
        !           233:        x = gen_rtx (GET_CODE (x), Pmode, op0, op1);
        !           234:     }
        !           235:   return x;
        !           236: }
        !           237: 
        !           238: /* Return something equivalent to X but valid as a memory address
        !           239:    for something of mode MODE.  When X is not itself valid, this
        !           240:    works by copying X or subexpressions of it into registers.  */
        !           241: 
        !           242: rtx
        !           243: memory_address (mode, x)
        !           244:      enum machine_mode mode;
        !           245:      register rtx x;
        !           246: {
        !           247:   register rtx tem, oldx;
        !           248: 
        !           249:   /* By passing constant addresses thru registers
        !           250:      we get a chance to cse them.  */
        !           251:   if (! cse_not_expected && CONSTANT_P (x))
        !           252:     return force_reg (Pmode, x);
        !           253: 
        !           254:   /* Accept a QUEUED that refers to a REG
        !           255:      even though that isn't a valid address.
        !           256:      On attempting to put this in an insn we will call protect_from_queue
        !           257:      which will turn it into a REG, which is valid.  */
        !           258:   if (GET_CODE (x) == QUEUED
        !           259:       && GET_CODE (QUEUED_VAR (x)) == REG)
        !           260:     return x;
        !           261: 
        !           262:   /* We get better cse by rejecting indirect addressing at this stage.
        !           263:      Let the combiner create indirect addresses where appropriate.
        !           264:      For now, generate the code so that the subexpressions useful to share
        !           265:      are visible.  But not if cse won't be done!  */
        !           266:   oldx = x;
        !           267:   if (! cse_not_expected && GET_CODE (x) != REG)
        !           268:     x = break_out_memory_refs (x);
        !           269: 
        !           270:   /* At this point, any valid address is accepted.  */
        !           271:   GO_IF_LEGITIMATE_ADDRESS (mode, x, win);
        !           272: 
        !           273:   /* If it was valid before but breaking out memory refs invalidated it,
        !           274:      use it the old way.  */
        !           275:   if (memory_address_p (mode, oldx))
        !           276:     goto win2;
        !           277: 
        !           278:   /* Perform machine-dependent transformations on X
        !           279:      in certain cases.  This is not necessary since the code
        !           280:      below can handle all possible cases, but machine-dependent
        !           281:      transformations can make better code.  */
        !           282:   LEGITIMIZE_ADDRESS (x, oldx, mode, win);
        !           283: 
        !           284:   /* PLUS and MULT can appear in special ways
        !           285:      as the result of attempts to make an address usable for indexing.
        !           286:      Usually they are dealt with by calling force_operand, below.
        !           287:      But a sum containing constant terms is special
        !           288:      if removing them makes the sum a valid address:
        !           289:      then we generate that address in a register
        !           290:      and index off of it.  We do this because it often makes
        !           291:      shorter code, and because the addresses thus generated
        !           292:      in registers often become common subexpressions.  */
        !           293:   if (GET_CODE (x) == PLUS)
        !           294:     {
        !           295:       int constant_term = 0;
        !           296:       rtx y = eliminate_constant_term (x, &constant_term);
        !           297:       if (constant_term == 0
        !           298:          || ! memory_address_p (mode, y))
        !           299:        return force_operand (x, 0);
        !           300: 
        !           301:       y = plus_constant (copy_to_reg (y), constant_term);
        !           302:       if (! memory_address_p (mode, y))
        !           303:        return force_operand (x, 0);
        !           304:       return y;
        !           305:     }
        !           306:   if (GET_CODE (x) == MULT || GET_CODE (x) == MINUS)
        !           307:     return force_operand (x, 0);
        !           308: 
        !           309:   /* Last resort: copy the value to a register, since
        !           310:      the register is a valid address.  */
        !           311:   return force_reg (Pmode, x);
        !           312: 
        !           313:  win2:
        !           314:   x = oldx;
        !           315:  win:
        !           316:   if (flag_force_addr && optimize && GET_CODE (x) != REG
        !           317:       /* Don't copy an addr via a reg if it is one of our stack slots.
        !           318:         If we did, it would cause invalid REG_EQUIV notes for parms.  */
        !           319:       && ! (GET_CODE (x) == PLUS
        !           320:            && (XEXP (x, 0) == frame_pointer_rtx
        !           321:                || XEXP (x, 0) == arg_pointer_rtx)))
        !           322:     return force_reg (Pmode, x);
        !           323:   return x;
        !           324: }
        !           325: 
        !           326: /* Return a modified copy of X with its memory address copied
        !           327:    into a temporary register to protect it from side effects.
        !           328:    If X is not a MEM, it is returned unchanged (and not copied).
        !           329:    Perhaps even if it is a MEM, if there is no need to change it.  */
        !           330: 
        !           331: rtx
        !           332: stabilize (x)
        !           333:      rtx x;
        !           334: {
        !           335:   register rtx addr;
        !           336:   if (GET_CODE (x) != MEM)
        !           337:     return x;
        !           338:   addr = XEXP (x, 0);
        !           339:   if (rtx_unstable_p (addr))
        !           340:     {
        !           341:       rtx temp = copy_all_regs (addr);
        !           342:       rtx mem;
        !           343:       if (GET_CODE (temp) != REG)
        !           344:        temp = copy_to_reg (temp);
        !           345:       mem = gen_rtx (MEM, GET_MODE (x), temp);
        !           346:       /* Mark returned memref with in_struct
        !           347:         if it's in an array or structure. */
        !           348:       if (GET_CODE (addr) == PLUS || x->in_struct)
        !           349:        mem->in_struct = 1;
        !           350:       return mem;
        !           351:     }
        !           352:   return x;
        !           353: }
        !           354: 
        !           355: /* Copy the value or contents of X to a new temp reg and return that reg.  */
        !           356: 
        !           357: rtx
        !           358: copy_to_reg (x)
        !           359:      rtx x;
        !           360: {
        !           361:   register rtx temp = gen_reg_rtx (GET_MODE (x));
        !           362:   emit_move_insn (temp, x);
        !           363:   return temp;
        !           364: }
        !           365: 
        !           366: /* Like copy_to_reg but always give the new register mode Pmode
        !           367:    in case X is a constant.  */
        !           368: 
        !           369: rtx
        !           370: copy_addr_to_reg (x)
        !           371:      rtx x;
        !           372: {
        !           373:   register rtx temp = gen_reg_rtx (Pmode);
        !           374:   emit_move_insn (temp, x);
        !           375:   return temp;
        !           376: }
        !           377: 
        !           378: /* Like copy_to_reg but always give the new register mode MODE
        !           379:    in case X is a constant.  */
        !           380: 
        !           381: rtx
        !           382: copy_to_mode_reg (mode, x)
        !           383:      enum machine_mode mode;
        !           384:      rtx x;
        !           385: {
        !           386:   register rtx temp = gen_reg_rtx (mode);
        !           387:   if (GET_MODE (x) != mode && GET_MODE (x) != VOIDmode)
        !           388:     abort ();
        !           389:   emit_move_insn (temp, x);
        !           390:   return temp;
        !           391: }
        !           392: 
        !           393: /* Load X into a register if it is not already one.
        !           394:    Use mode MODE for the register.
        !           395:    X should be valid for mode MODE, but it may be a constant which
        !           396:    is valid for all integer modes; that's why caller must specify MODE.
        !           397: 
        !           398:    The caller must not alter the value in the register we return,
        !           399:    since we mark it as a "constant" register.  */
        !           400: 
        !           401: rtx
        !           402: force_reg (mode, x)
        !           403:      enum machine_mode mode;
        !           404:      rtx x;
        !           405: {
        !           406:   register rtx temp, insn;
        !           407: 
        !           408:   if (GET_CODE (x) == REG)
        !           409:     return x;
        !           410:   temp = gen_reg_rtx (mode);
        !           411:   insn = emit_move_insn (temp, x);
        !           412:   /* Let optimizers know that TEMP's value never changes
        !           413:      and that X can be substituted for it.  */
        !           414:   if (CONSTANT_P (x))
        !           415:     REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUIV, x, 0);
        !           416:   return temp;
        !           417: }
        !           418: 
        !           419: /* If X is a memory ref, copy its contents to a new temp reg and return
        !           420:    that reg.  Otherwise, return X.  */
        !           421: 
        !           422: rtx
        !           423: force_not_mem (x)
        !           424:      rtx x;
        !           425: {
        !           426:   register rtx temp;
        !           427:   if (GET_CODE (x) != MEM)
        !           428:     return x;
        !           429:   temp = gen_reg_rtx (GET_MODE (x));
        !           430:   emit_move_insn (temp, x);
        !           431:   return temp;
        !           432: }
        !           433: 
        !           434: /* Copy X to TARGET (if it's nonzero and a reg)
        !           435:    or to a new temp reg and return that reg.  */
        !           436: 
        !           437: rtx
        !           438: copy_to_suggested_reg (x, target)
        !           439:      rtx x, target;
        !           440: {
        !           441:   register rtx temp;
        !           442:   if (target && GET_CODE (target) == REG)
        !           443:     temp = target;
        !           444:   else
        !           445:     temp = gen_reg_rtx (GET_MODE (x));
        !           446:   emit_move_insn (temp, x);
        !           447:   return temp;
        !           448: }
        !           449: 
        !           450: /* Adjust the stack pointer by ADJUST (an rtx for a number of bytes).
        !           451:    This pops when ADJUST is positive.  ADJUST need not be constant.  */
        !           452: 
        !           453: void
        !           454: adjust_stack (adjust)
        !           455:      rtx adjust;
        !           456: {
        !           457:   adjust = protect_from_queue (adjust, 0);
        !           458: 
        !           459: #ifdef STACK_GROWS_DOWNWARD
        !           460:   emit_insn (gen_add2_insn (stack_pointer_rtx, adjust));
        !           461: #else
        !           462:   emit_insn (gen_sub2_insn (stack_pointer_rtx, adjust));
        !           463: #endif
        !           464: }
        !           465: 
        !           466: /* Adjust the stack pointer by minus ADJUST (an rtx for a number of bytes).
        !           467:    This pushes when ADJUST is positive.  ADJUST need not be constant.  */
        !           468: 
        !           469: void
        !           470: anti_adjust_stack (adjust)
        !           471:      rtx adjust;
        !           472: {
        !           473:   adjust = protect_from_queue (adjust, 0);
        !           474: 
        !           475: #ifdef STACK_GROWS_DOWNWARD
        !           476:   emit_insn (gen_sub2_insn (stack_pointer_rtx, adjust));
        !           477: #else
        !           478:   emit_insn (gen_add2_insn (stack_pointer_rtx, adjust));
        !           479: #endif
        !           480: }
        !           481: 
        !           482: /* Round the size of a block to be pushed up to the boundary required
        !           483:    by this machine.  SIZE is the desired size, which need not be constant.  */
        !           484: 
        !           485: rtx
        !           486: round_push (size)
        !           487:      rtx size;
        !           488: {
        !           489: #ifdef STACK_BOUNDARY
        !           490:   int align = STACK_BOUNDARY / BITS_PER_UNIT;
        !           491:   if (align == 1)
        !           492:     ;
        !           493:   if (GET_CODE (size) == CONST_INT)
        !           494:     {
        !           495:       int new = (INTVAL (size) + align - 1) / align * align;
        !           496:       if (INTVAL (size) != new)
        !           497:        size = gen_rtx (CONST_INT, VOIDmode, new);
        !           498:     }
        !           499:   else
        !           500:     {
        !           501:       size = expand_divmod (0, CEIL_DIV_EXPR, Pmode, size,
        !           502:                            gen_rtx (CONST_INT, VOIDmode, align),
        !           503:                            0, 1);
        !           504:       size = expand_mult (Pmode, size,
        !           505:                          gen_rtx (CONST_INT, VOIDmode, align),
        !           506:                          0, 1);
        !           507:     }
        !           508: #endif /* STACK_BOUNDARY */
        !           509:   return size;
        !           510: }
        !           511: 
        !           512: /* Return an rtx representing the register or memory location
        !           513:    in which a scalar value of data type VALTYPE
        !           514:    was returned by a function call to function FUNC.
        !           515:    FUNC is a FUNCTION_DECL node if the precise function is known,
        !           516:    otherwise 0.  */
        !           517: 
        !           518: rtx
        !           519: hard_function_value (valtype, func)
        !           520:      tree valtype;
        !           521:      tree func;
        !           522: {
        !           523:   return FUNCTION_VALUE (valtype, func);
        !           524: }
        !           525: 
        !           526: /* Return an rtx representing the register or memory location
        !           527:    in which a scalar value of mode MODE was returned by a library call.  */
        !           528: 
        !           529: rtx
        !           530: hard_libcall_value (mode)
        !           531:      enum machine_mode mode;
        !           532: {
        !           533:   return LIBCALL_VALUE (mode);
        !           534: }

unix.superglobalmegacorp.com

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