📄 explow.c
字号:
But a sum containing constant terms is special if removing them makes the sum a valid address: then we generate that address in a register and index off of it. We do this because it often makes shorter code, and because the addresses thus generated in registers often become common subexpressions. */ if (GET_CODE (x) == PLUS) { int constant_term = 0; rtx y = eliminate_constant_term (x, &constant_term); if (constant_term == 0 || ! memory_address_p (mode, y)) return force_operand (x, 0); y = plus_constant (copy_to_reg (y), constant_term); if (! memory_address_p (mode, y)) return force_operand (x, 0); return y; } if (GET_CODE (x) == MULT || GET_CODE (x) == MINUS) return force_operand (x, 0); /* If we have a register that's an invalid address, it must be a hard reg of the wrong class. Copy it to a pseudo. */ if (GET_CODE (x) == REG) return copy_to_reg (x); /* Last resort: copy the value to a register, since the register is a valid address. */ return force_reg (Pmode, x); win2: x = oldx; win: if (flag_force_addr && optimize && GET_CODE (x) != REG /* Don't copy an addr via a reg if it is one of our stack slots. If we did, it would cause invalid REG_EQUIV notes for parms. */ && ! (GET_CODE (x) == PLUS && (XEXP (x, 0) == frame_pointer_rtx || XEXP (x, 0) == arg_pointer_rtx))) { if (general_operand (x, Pmode)) return force_reg (Pmode, x); else return force_operand (x, 0); } return x;}/* Like `memory_address' but pretend `flag_force_addr' is 0. */rtxmemory_address_noforce (mode, x) enum machine_mode mode; rtx x;{ int ambient_force_addr = flag_force_addr; rtx val; flag_force_addr = 0; val = memory_address (mode, x); flag_force_addr = ambient_force_addr; return val;}/* Return a modified copy of X with its memory address copied into a temporary register to protect it from side effects. If X is not a MEM, it is returned unchanged (and not copied). Perhaps even if it is a MEM, if there is no need to change it. */rtxstabilize (x) rtx x;{ register rtx addr; if (GET_CODE (x) != MEM) return x; addr = XEXP (x, 0); if (rtx_unstable_p (addr)) { rtx temp = copy_all_regs (addr); rtx mem; if (GET_CODE (temp) != REG) temp = copy_to_reg (temp); mem = gen_rtx (MEM, GET_MODE (x), temp); /* Mark returned memref with in_struct if it's in an array or structure. */ if (GET_CODE (addr) == PLUS || MEM_IN_STRUCT_P (x)) MEM_IN_STRUCT_P (mem) = 1; return mem; } return x;}/* Copy the value or contents of X to a new temp reg and return that reg. */rtxcopy_to_reg (x) rtx x;{ register rtx temp = gen_reg_rtx (GET_MODE (x)); /* If not an operand, must be an address with PLUS and MULT so do the computation. */ if (! general_operand (x, VOIDmode)) x = force_operand (x, temp); if (x != temp) emit_move_insn (temp, x); return temp;}/* Like copy_to_reg but always give the new register mode Pmode in case X is a constant. */rtxcopy_addr_to_reg (x) rtx x;{ return copy_to_mode_reg (Pmode, x);}/* Like copy_to_reg but always give the new register mode MODE in case X is a constant. */rtxcopy_to_mode_reg (mode, x) enum machine_mode mode; rtx x;{ register rtx temp = gen_reg_rtx (mode); /* If not an operand, must be an address with PLUS and MULT so do the computation. */ if (! general_operand (x, VOIDmode)) x = force_operand (x, temp); if (GET_MODE (x) != mode && GET_MODE (x) != VOIDmode) abort (); if (x != temp) emit_move_insn (temp, x); return temp;}/* Load X into a register if it is not already one. Use mode MODE for the register. X should be valid for mode MODE, but it may be a constant which is valid for all integer modes; that's why caller must specify MODE. The caller must not alter the value in the register we return, since we mark it as a "constant" register. */rtxforce_reg (mode, x) enum machine_mode mode; rtx x;{ register rtx temp, insn; if (GET_CODE (x) == REG) return x; temp = gen_reg_rtx (mode); insn = emit_move_insn (temp, x); /* Let optimizers know that TEMP's value never changes and that X can be substituted for it. */ if (CONSTANT_P (x)) REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUIV, x, REG_NOTES (insn)); return temp;}/* If X is a memory ref, copy its contents to a new temp reg and return that reg. Otherwise, return X. */rtxforce_not_mem (x) rtx x;{ register rtx temp; if (GET_CODE (x) != MEM || GET_MODE (x) == BLKmode) return x; temp = gen_reg_rtx (GET_MODE (x)); emit_move_insn (temp, x); return temp;}/* Copy X to TARGET (if it's nonzero and a reg) or to a new temp reg and return that reg. */rtxcopy_to_suggested_reg (x, target) rtx x, target;{ register rtx temp; if (target && GET_CODE (target) == REG) temp = target; else temp = gen_reg_rtx (GET_MODE (x)); emit_move_insn (temp, x); return temp;}/* Adjust the stack pointer by ADJUST (an rtx for a number of bytes). This pops when ADJUST is positive. ADJUST need not be constant. */voidadjust_stack (adjust) rtx adjust;{ adjust = protect_from_queue (adjust, 0);#ifdef STACK_GROWS_DOWNWARD emit_insn (gen_add2_insn (stack_pointer_rtx, adjust));#else emit_insn (gen_sub2_insn (stack_pointer_rtx, adjust));#endif}/* Adjust the stack pointer by minus ADJUST (an rtx for a number of bytes). This pushes when ADJUST is positive. ADJUST need not be constant. */voidanti_adjust_stack (adjust) rtx adjust;{ adjust = protect_from_queue (adjust, 0);#ifdef STACK_GROWS_DOWNWARD emit_insn (gen_sub2_insn (stack_pointer_rtx, adjust));#else emit_insn (gen_add2_insn (stack_pointer_rtx, adjust));#endif}/* Round the size of a block to be pushed up to the boundary required by this machine. SIZE is the desired size, which need not be constant. */rtxround_push (size) rtx size;{#ifdef STACK_BOUNDARY int align = STACK_BOUNDARY / BITS_PER_UNIT; if (align == 1) return size; if (GET_CODE (size) == CONST_INT) { int new = (INTVAL (size) + align - 1) / align * align; if (INTVAL (size) != new) size = gen_rtx (CONST_INT, VOIDmode, new); } else { size = expand_divmod (0, CEIL_DIV_EXPR, Pmode, size, gen_rtx (CONST_INT, VOIDmode, align), 0, 1); size = expand_mult (Pmode, size, gen_rtx (CONST_INT, VOIDmode, align), 0, 1); }#endif /* STACK_BOUNDARY */ return size;}/* Return an rtx representing the register or memory location in which a scalar value of data type VALTYPE was returned by a function call to function FUNC. FUNC is a FUNCTION_DECL node if the precise function is known, otherwise 0. */rtxhard_function_value (valtype, func) tree valtype; tree func;{ return FUNCTION_VALUE (valtype, func);}/* Return an rtx representing the register or memory location in which a scalar value of mode MODE was returned by a library call. */rtxhard_libcall_value (mode) enum machine_mode mode;{ return LIBCALL_VALUE (mode);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -