Annotation of researchv10dc/cmd/gcc/explow.c, revision 1.1.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.