gcc-8.3/gcc/eliminate_regs_1()
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
|
ログイン
]
開始行:
*参照元 [#wa845a63]
#backlinks
*説明 [#qcb8cbf8]
-パス: [[gcc-8.3/gcc/reload1.c]]
-FIXME: これは何?
--説明
--
---riscv の一例だと、65 frame を 2 sp に置き換える。
--置き換える元は reg_eliminate に定義されている。テーブル...
---[[gcc-8.3/gcc/reg_eliminate(global)]]
---[[gcc-8.3/gcc/init_elim_table()]]
**引数 [#u700b1fa]
-rtx x
--
--[[gcc-8.3/gcc/rtx]]
-machine_mode mem_mode
--
--[[gcc-8.3/gcc/machine_mode]]
-rtx insn
--
-bool may_use_invariant
--
-bool for_costs
--
**返り値 [#x5e01f79]
-rtx
--
--[[gcc-8.3/gcc/rtx]]
**参考 [#t9710a6b]
*実装 [#dfceba00]
/* Scan X and replace any eliminable registers (such as ...
replacement (such as sp), plus an offset.
MEM_MODE is the mode of an enclosing MEM. We need th...
much to adjust a register for, e.g., PRE_DEC. Also, ...
MEM, we are allowed to replace a sum of a register an...
with the register, which we cannot do outside a MEM. ...
to record the fact that a register is referenced outs...
If INSN is an insn, it is the insn containing X. If ...
in a SET_DEST with an equivalent MEM and INSN is nonz...
CLOBBER of the pseudo after INSN so find_equiv_regs w...
the REG is being modified.
Alternatively, INSN may be a note (an EXPR_LIST or IN...
That's used when we eliminate in expressions stored i...
This means, do not set ref_outside_mem even if the re...
is outside of MEMs.
If FOR_COSTS is true, we are being called before relo...
estimate the costs of keeping registers with an equiv...
REG_EQUIV_MEM and REG_EQUIV_ADDRESS contain address t...
replacements done assuming all offsets are at their i...
they are not, or if REG_EQUIV_ADDRESS is nonzero for ...
encounter, return the actual location so that find_re...
the proper thing. */
static rtx
eliminate_regs_1 (rtx x, machine_mode mem_mode, rtx insn,
bool may_use_invariant, bool for_costs)
{
enum rtx_code code = GET_CODE (x);
struct elim_table *ep;
int regno;
rtx new_rtx;
int i, j;
const char *fmt;
int copied = 0;
-
--[[gcc-8.3/gcc/rtx_code]]
--[[gcc-8.3/gcc/GET_CODE()]]
if (! current_function_decl)
return x;
switch (code)
{
CASE_CONST_ANY:
case CONST:
case SYMBOL_REF:
case CODE_LABEL:
case PC:
case CC0:
case ASM_INPUT:
case ADDR_VEC:
case ADDR_DIFF_VEC:
case RETURN:
return x;
case REG:
regno = REGNO (x);
/* First handle the case where we encounter a bare...
is eliminable. Replace it with a PLUS. */
if (regno < FIRST_PSEUDO_REGISTER)
{
for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIM...
ep++)
if (ep->from_rtx == x && ep->can_eliminate)
return plus_constant (Pmode, ep->to_rtx, ep->prev...
}
else if (reg_renumber && reg_renumber[regno] < 0
&& reg_equivs
&& reg_equiv_invariant (regno))
{
if (may_use_invariant || (insn && DEBUG_INSN_P (insn)))
return eliminate_regs_1 (copy_rtx (reg_equiv_invari...
mem_mode, insn, true, for_costs);
/* There exists at least one use of REGNO that cannot...
eliminated. Prevent the defining insn from being ...
reg_equiv_init (regno) = NULL;
if (!for_costs)
alter_reg (regno, -1, true);
}
return x;
-
--[[gcc-8.3/gcc/REGNO()]]
--[[gcc-8.3/gcc/reg_eliminate(global)]]
--[[gcc-8.3/gcc/plus_constant()]]
--[[gcc-8.3/gcc/reg_equiv_invariant()]]
--[[gcc-8.3/gcc/DEBUG_INSN_P()]]
--[[gcc-8.3/gcc/eliminate_regs_1()]]
--[[gcc-8.3/gcc/copy_rtx()]]
--[[gcc-8.3/gcc/reg_equiv_init()]]
--[[gcc-8.3/gcc/alter_reg()]]
/* You might think handling MINUS in a manner simila...
good idea. It is not. It has been tried multipl...
time the change has had to have been reverted.
Other parts of reload know a PLUS is special (gen...
and require special code to handle code a reloade...
Also consider backends where the flags register i...
MINUS, but we can emit a PLUS that does not clobb...
lea instruction comes to mind). If we try to rel...
may kill the flags register that was holding a us...
So, please before trying to handle MINUS, conside...
whole instead of this little section as well as t...
case PLUS:
/* If this is the sum of an eliminable register an...
the sum. */
if (REG_P (XEXP (x, 0))
&& REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
&& CONSTANT_P (XEXP (x, 1)))
{
for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIM...
ep++)
if (ep->from_rtx == XEXP (x, 0) && ep->can_eliminate)
{
/* The only time we want to replace a PLUS with a REG ...
occurs when the constant operand of the PLUS is the...
of the offset) is when we are inside a MEM. We won...
to do so at other times because that would change the
structure of the insn in a way that reload can't ha...
We special-case the commonest situation in
eliminate_regs_in_insn, so just replace a PLUS with a
PLUS here, unless inside a MEM. */
rtx _t;
if (mem_mode != 0
&& CONST_INT_P (XEXP (x, 1))
&& known_eq (INTVAL (XEXP (x, 1)), -ep->previous_o...
return ep->to_rtx;
else
return gen_rtx_PLUS (Pmode, ep->to_rtx,
plus_constant (Pmode, XEXP (x, 1),
ep->previous_offset));
}
}
/* If the register is not eliminable, we are done sin...
operand is a constant. */
return x;
}
-
--[[gcc-8.3/gcc/REGP()]]
--[[gcc-8.3/gcc/XEXP()]]
--[[gcc-8.3/gcc/REGNO()]]
--[[gcc-8.3/gcc/CONSTANT_P()]]
--[[gcc-8.3/gcc/reg_eliminate(global)]]
--[[gcc-8.3/gcc/CONST_INT_P()]]
--[[gcc-8.3/gcc/known_eq()]]
--[[gcc-8.3/gcc/INTVAL()]]
--[[gcc-8.3/gcc/gen_rtx_PLUS()]]
--[[gcc-8.3/gcc/plus_constant()]]
/* If this is part of an address, we want to bring...
outermost PLUS. We will do this by doing register rep...
our operands and seeing if a constant shows up in one ...
Note that there is no risk of modifying the structure ...
since we only get called for its operands, thus we are...
modifying the address inside a MEM, or something like ...
operand of a load-address insn. */
{
rtx new0 = eliminate_regs_1 (XEXP (x, 0), mem_mode, ins...
for_costs);
rtx new1 = eliminate_regs_1 (XEXP (x, 1), mem_mode, ins...
for_costs);
if (reg_renumber && (new0 != XEXP (x, 0) || new1 != XEX...
{
/* If one side is a PLUS and the other side is a ps...
didn't get a hard register but has a reg_equiv_c...
we must replace the constant here since it may n...
be in the position of any operand. */
if (GET_CODE (new0) == PLUS && REG_P (new1)
&& REGNO (new1) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[REGNO (new1)] < 0
&& reg_equivs
&& reg_equiv_constant (REGNO (new1)) != 0)
new1 = reg_equiv_constant (REGNO (new1));
else if (GET_CODE (new1) == PLUS && REG_P (new0)
&& REGNO (new0) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[REGNO (new0)] < 0
&& reg_equiv_constant (REGNO (new0)) != 0)
new0 = reg_equiv_constant (REGNO (new0));
new_rtx = form_sum (GET_MODE (x), new0, new1);
/* As above, if we are not inside a MEM we do not w...
turn a PLUS into something else. We might try t...
for an addition of 0 if we aren't optimizing. */
if (! mem_mode && GET_CODE (new_rtx) != PLUS)
return gen_rtx_PLUS (GET_MODE (x), new_rtx, const...
else
return new_rtx;
}
}
return x;
-
--[[gcc-8.3/gcc/XEXP()]]
--[[gcc-8.3/gcc/GET_CODE()]]
--[[gcc-8.3/gcc/REG_P()]]
--[[gcc-8.3/gcc/REGNO()]]
--[[gcc-8.3/gcc/reg_equiv_constant()]]
--[[gcc-8.3/gcc/form_sum()]]
--[[gcc-8.3/gcc/GET_MODE()]]
--[[gcc-8.3/gcc/gen_rtx_PLUS()]]
case MULT:
/* If this is the product of an eliminable registe...
constant, apply the distribute law and move the consta...
so that we have (plus (mult ..) ..). This is needed i...
to keep load-address insns valid. This case is patho...
We ignore the possibility of overflow here. */
if (REG_P (XEXP (x, 0))
&& REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
&& CONST_INT_P (XEXP (x, 1)))
for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMIN...
ep++)
if (ep->from_rtx == XEXP (x, 0) && ep->can_eliminate)
{
if (! mem_mode
/* Refs inside notes or in DEBUG_INSNs don't count for
this purpose. */
&& ! (insn != 0 && (GET_CODE (insn) == EXPR_LIST
|| GET_CODE (insn) == INSN_LIST
|| DEBUG_INSN_P (insn))))
ep->ref_outside_mem = 1;
return
plus_constant (Pmode,
gen_rtx_MULT (Pmode, ep->to_rtx, XEXP (x, 1)),
ep->previous_offset * INTVAL (XEXP (x, 1)));
}
-
--[[gcc-8.3/gcc/REG_P()]]
--[[gcc-8.3/gcc/REGNO()]]
--[[gcc-8.3/gcc/XEXP()]]
--[[gcc-8.3/gcc/CONST_INT_P()]]
--[[gcc-8.3/gcc/GET_CODE()]]
--[[gcc-8.3/gcc/DEBUG_INSN_P()]]
--[[gcc-8.3/gcc/plus_constant()]]
--[[gcc-8.3/gcc/gen_rtx_MULT()]]
--[[gcc-8.3/gcc/INTVAL()]]
/* fall through */
case CALL:
case COMPARE:
/* See comments before PLUS about handling MINUS. */
case MINUS:
case DIV: case UDIV:
case MOD: case UMOD:
case AND: case IOR: case XOR:
case ROTATERT: case ROTATE:
case ASHIFTRT: case LSHIFTRT: case ASHIFT:
case NE: case EQ:
case GE: case GT: case GEU: case GTU:
case LE: case LT: case LEU: case LTU:
{
rtx new0 = eliminate_regs_1 (XEXP (x, 0), mem_mode, ins...
for_costs);
rtx new1 = XEXP (x, 1)
? eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, false,
for_costs) : 0;
if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
return gen_rtx_fmt_ee (code, GET_MODE (x), new0, new1);
}
return x;
-
--[[gcc-8.3/gcc/eliminate_regs_1()]]
--[[gcc-8.3/gcc/XEXP()]]
--[[gcc-8.3/gcc/GET_MODE()]]
--[[gcc-8.3/gcc/gen_rtx_fmt_ee()]]
case EXPR_LIST:
/* If we have something in XEXP (x, 0), the usual ...
if (XEXP (x, 0))
{
new_rtx = eliminate_regs_1 (XEXP (x, 0), mem_mode, in...
for_costs);
if (new_rtx != XEXP (x, 0))
{
/* If this is a REG_DEAD note, it is not valid an...
Using the eliminated version could result in creating a
REG_DEAD note for the stack or frame pointer. */
if (REG_NOTE_KIND (x) == REG_DEAD)
return (XEXP (x, 1)
? eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true,
for_costs)
: NULL_RTX);
x = alloc_reg_note (REG_NOTE_KIND (x), new_rtx, X...
}
}
/* fall through */
-
--[[gcc-8.3/gcc/XEXP()]]
--[[gcc-8.3/gcc/eliminate_regs_1()]]
--[[gcc-8.3/gcc/REG_NOTE_KIND()]]
--[[gcc-8.3/gcc/alloc_reg_note()]]
case INSN_LIST:
case INT_LIST:
/* Now do eliminations in the rest of the chain. ...
an EXPR_LIST, this might result in allocating more mem...
strictly needed, but it simplifies the code. */
if (XEXP (x, 1))
{
new_rtx = eliminate_regs_1 (XEXP (x, 1), mem_mode, in...
for_costs);
if (new_rtx != XEXP (x, 1))
return
gen_rtx_fmt_ee (GET_CODE (x), GET_MODE (x), XEXP ...
}
return x;
-
--[[gcc-8.3/gcc/XEXP()]]
--[[gcc-8.3/gcc/eliminate_regs_1()]]
--[[gcc-8.3/gcc/gen_rtx_fmt_ee()]]
--[[gcc-8.3/gcc/GET_CODE()]]
case PRE_INC:
case POST_INC:
case PRE_DEC:
case POST_DEC:
/* We do not support elimination of a register tha...
elimination_effects has already make sure that this do...
happen. */
return x;
case PRE_MODIFY:
case POST_MODIFY:
/* We do not support elimination of a register tha...
elimination_effects has already make sure that this do...
happen. The only remaining case we need to consider h...
that the increment value may be an eliminable register...
if (GET_CODE (XEXP (x, 1)) == PLUS
&& XEXP (XEXP (x, 1), 0) == XEXP (x, 0))
{
rtx new_rtx = eliminate_regs_1 (XEXP (XEXP (x, 1), 1)...
insn, true, for_costs);
if (new_rtx != XEXP (XEXP (x, 1), 1))
return gen_rtx_fmt_ee (code, GET_MODE (x), XEXP (x,...
gen_rtx_PLUS (GET_MODE (x),
XEXP (x, 0), new_rtx));
}
return x;
-
--[[gcc-8.3/gcc/GET_CODE()]]
--[[gcc-8.3/gcc/XEXP()]]
--[[gcc-8.3/gcc/elieminate_regs_1()]]
--[[gcc-8.3/gcc/gen_rtx_fmt_ee()]]
--[[gcc-8.3/gcc/GET_MODE()]]
--[[gcc-8.3/gcc/gen_rtx_PLUS()]]
case STRICT_LOW_PART:
case NEG: case NOT:
case SIGN_EXTEND: case ZERO_EXTEND:
case TRUNCATE: case FLOAT_EXTEND: case FLOAT_TRU...
case FLOAT: case FIX:
case UNSIGNED_FIX: case UNSIGNED_FLOAT:
case ABS:
case SQRT:
case FFS:
case CLZ:
case CTZ:
case POPCOUNT:
case PARITY:
case BSWAP:
new_rtx = eliminate_regs_1 (XEXP (x, 0), mem_mode,...
for_costs);
if (new_rtx != XEXP (x, 0))
return gen_rtx_fmt_e (code, GET_MODE (x), new_rtx);
return x;
-
--[[gcc-8.3/gcc/eliminate_regs_1()]]
--[[gcc-8.3/gcc/XEXP()]]
--[[gcc-8.3/gcc/gen_rtx_fmt_e()]]
--[[gcc-8.3/gcc/GET_MODE()]]
case SUBREG:
/* Similar to above processing, but preserve SUBRE...
Convert (subreg (mem)) to (mem) if not paradoxical.
Also, if we have a non-paradoxical (subreg (pseudo)) a...
pseudo didn't get a hard reg, we must replace this wit...
eliminated version of the memory location because push...
may do the replacement in certain circumstances. */
if (REG_P (SUBREG_REG (x))
&& !paradoxical_subreg_p (x)
&& reg_equivs
&& reg_equiv_memory_loc (REGNO (SUBREG_REG (x))) != 0)
{
new_rtx = SUBREG_REG (x);
}
else
new_rtx = eliminate_regs_1 (SUBREG_REG (x), mem_mode, i...
-
--[[gcc-8.3/gcc/REG_P()]]
--[[gcc-8.3/gcc/SUBREG_REG()]]
--[[gcc-8.3/gcc/paradoxical_subreg_p()]]
--[[gcc-8.3/gcc/REGNO()]]
--[[gcc-8.3/gcc/reg_equiv_memory_loc()]]
--[[gcc-8.3/gcc/eliminate_regs_1()]]
if (new_rtx != SUBREG_REG (x))
{
poly_int64 x_size = GET_MODE_SIZE (GET_MODE (x));
poly_int64 new_size = GET_MODE_SIZE (GET_MODE (new_rt...
if (MEM_P (new_rtx)
&& ((partial_subreg_p (GET_MODE (x), GET_MODE (ne...
/* On RISC machines, combine can create rtl of the ...
(set (subreg:m1 (reg:m2 R) 0) ...)
where m1 < m2, and expects something interesting...
happen to the entire word. Moreover, it will us...
(reg:m2 R) later, expecting all bits to be prese...
So if the number of words is the same, preserve ...
subreg so that push_reload can see it. */
&& !(WORD_REGISTER_OPERATIONS
&& known_equal_after_align_down (x_size - 1,
new_size - 1,
UNITS_PER_WORD)))
|| known_eq (x_size, new_size))
)
return adjust_address_nv (new_rtx, GET_MODE (x), SU...
else if (insn && GET_CODE (insn) == DEBUG_INSN)
return gen_rtx_raw_SUBREG (GET_MODE (x), new_rtx, S...
else
return gen_rtx_SUBREG (GET_MODE (x), new_rtx, SUBRE...
}
return x;
-
--[[gcc-8.3/gcc/poly_int64]]
--[[gcc-8.3/gcc/GET_MODE_SIZE()]]
--[[gcc-8.3/gcc/GET_MODE()]]
--[[gcc-8.3/gcc/MEM_P()]]
--[[gcc-8.3/gcc/partial_subreg_p()]]
--[[gcc-8.3/gcc/known_equal_after_align_down()]]
--[[gcc-8.3/gcc/known_eq()]]
--[[gcc-8.3/gcc/adjust_address_nv()]]
--[[gcc-8.3/gcc/SUBREG_BYTE()]]
--[[gcc-8.3/gcc/gen_rtx_raw_SUBREG()]]
--[[gcc-8.3/gcc/gen_rtx_SUBREG()]]
case MEM:
/* Our only special processing is to pass the mode...
recursive call and copy the flags. While we are here,...
case more efficiently. */
new_rtx = eliminate_regs_1 (XEXP (x, 0), GET_MODE ...
for_costs);
if (for_costs
&& memory_address_p (GET_MODE (x), XEXP (x, 0))
&& !memory_address_p (GET_MODE (x), new_rtx))
note_reg_elim_costly (XEXP (x, 0), insn);
return replace_equiv_address_nv (x, new_rtx);
-
--[[gcc-8.3/gcc/eliminate_regs_1()]]
--[[gcc-8.3/gcc/XEXP()]]
--[[gcc-8.3/gcc/GET_MODE()]]
--[[gcc-8.3/gcc/memory_address_p()]]
--[[gcc-8.3/gcc/note_reg_elim_costly()]]
--[[gcc-8.3/gcc/replace_equiv_address_nv()]]
case USE:
/* Handle insn_list USE that a call to a pure func...
new_rtx = eliminate_regs_1 (XEXP (x, 0), VOIDmode,...
for_costs);
if (new_rtx != XEXP (x, 0))
return gen_rtx_USE (GET_MODE (x), new_rtx);
return x;
-
--[[gcc-8.3/gcc/eliminate_regs_1()]]
--[[gcc-8.3/gcc/XEXP()]]
--[[gcc-8.3/gcc/gen_rtx_USE()]]
--[[gcc-8.3/gcc/GET_MODE()]]
case CLOBBER:
case ASM_OPERANDS:
gcc_assert (insn && DEBUG_INSN_P (insn));
break;
-
--[[gcc-8.3/gcc/gcc_assert()]]
--[[gcc-8.3/gcc/DEBUG_INSN_P()]]
case SET:
gcc_unreachable ();
-
--[[gcc-8.3/gcc/gcc_unreachable()]]
default:
break;
}
/* Process each of our operands recursively. If any h...
copy of the rtx. */
fmt = GET_RTX_FORMAT (code);
for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
{
if (*fmt == 'e')
{
new_rtx = eliminate_regs_1 (XEXP (x, i), mem_mode, in...
for_costs);
if (new_rtx != XEXP (x, i) && ! copied)
{
x = shallow_copy_rtx (x);
copied = 1;
}
XEXP (x, i) = new_rtx;
}
-
--[[gcc-8.3/gcc/GET_RTX_FORMAT()]]
--[[gcc-8.3/gcc/GET_RTX_LENGTH()]]
--[[gcc-8.3/gcc/eliminate_regs_1()]]
--[[gcc-8.3/gcc/shallo_copy_rtx()]]
--[[gcc-8.3/gcc/XEXP()]]
else if (*fmt == 'E')
{
int copied_vec = 0;
for (j = 0; j < XVECLEN (x, i); j++)
{
new_rtx = eliminate_regs_1 (XVECEXP (x, i, j), me...
for_costs);
if (new_rtx != XVECEXP (x, i, j) && ! copied_vec)
{
rtvec new_v = gen_rtvec_v (XVECLEN (x, i),
XVEC (x, i)->elem);
if (! copied)
{
x = shallow_copy_rtx (x);
copied = 1;
}
XVEC (x, i) = new_v;
copied_vec = 1;
}
XVECEXP (x, i, j) = new_rtx;
}
}
-
--[[gcc-8.3/gcc/XVECLEN()]]
--[[gcc-8.3/gcc/eliminate_regs_1()]]
--[[gcc-8.3/gcc/XVECEXP()]]
--[[gcc-8.3/gcc/XVEC()]]
--[[gcc-8.3/gcc/gen_rtvec_v()]]
--[[gcc-8.3/gcc/shallow_copy_rtx()]]
}
return x;
}
*コメント [#q2d1c740]
終了行:
*参照元 [#wa845a63]
#backlinks
*説明 [#qcb8cbf8]
-パス: [[gcc-8.3/gcc/reload1.c]]
-FIXME: これは何?
--説明
--
---riscv の一例だと、65 frame を 2 sp に置き換える。
--置き換える元は reg_eliminate に定義されている。テーブル...
---[[gcc-8.3/gcc/reg_eliminate(global)]]
---[[gcc-8.3/gcc/init_elim_table()]]
**引数 [#u700b1fa]
-rtx x
--
--[[gcc-8.3/gcc/rtx]]
-machine_mode mem_mode
--
--[[gcc-8.3/gcc/machine_mode]]
-rtx insn
--
-bool may_use_invariant
--
-bool for_costs
--
**返り値 [#x5e01f79]
-rtx
--
--[[gcc-8.3/gcc/rtx]]
**参考 [#t9710a6b]
*実装 [#dfceba00]
/* Scan X and replace any eliminable registers (such as ...
replacement (such as sp), plus an offset.
MEM_MODE is the mode of an enclosing MEM. We need th...
much to adjust a register for, e.g., PRE_DEC. Also, ...
MEM, we are allowed to replace a sum of a register an...
with the register, which we cannot do outside a MEM. ...
to record the fact that a register is referenced outs...
If INSN is an insn, it is the insn containing X. If ...
in a SET_DEST with an equivalent MEM and INSN is nonz...
CLOBBER of the pseudo after INSN so find_equiv_regs w...
the REG is being modified.
Alternatively, INSN may be a note (an EXPR_LIST or IN...
That's used when we eliminate in expressions stored i...
This means, do not set ref_outside_mem even if the re...
is outside of MEMs.
If FOR_COSTS is true, we are being called before relo...
estimate the costs of keeping registers with an equiv...
REG_EQUIV_MEM and REG_EQUIV_ADDRESS contain address t...
replacements done assuming all offsets are at their i...
they are not, or if REG_EQUIV_ADDRESS is nonzero for ...
encounter, return the actual location so that find_re...
the proper thing. */
static rtx
eliminate_regs_1 (rtx x, machine_mode mem_mode, rtx insn,
bool may_use_invariant, bool for_costs)
{
enum rtx_code code = GET_CODE (x);
struct elim_table *ep;
int regno;
rtx new_rtx;
int i, j;
const char *fmt;
int copied = 0;
-
--[[gcc-8.3/gcc/rtx_code]]
--[[gcc-8.3/gcc/GET_CODE()]]
if (! current_function_decl)
return x;
switch (code)
{
CASE_CONST_ANY:
case CONST:
case SYMBOL_REF:
case CODE_LABEL:
case PC:
case CC0:
case ASM_INPUT:
case ADDR_VEC:
case ADDR_DIFF_VEC:
case RETURN:
return x;
case REG:
regno = REGNO (x);
/* First handle the case where we encounter a bare...
is eliminable. Replace it with a PLUS. */
if (regno < FIRST_PSEUDO_REGISTER)
{
for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIM...
ep++)
if (ep->from_rtx == x && ep->can_eliminate)
return plus_constant (Pmode, ep->to_rtx, ep->prev...
}
else if (reg_renumber && reg_renumber[regno] < 0
&& reg_equivs
&& reg_equiv_invariant (regno))
{
if (may_use_invariant || (insn && DEBUG_INSN_P (insn)))
return eliminate_regs_1 (copy_rtx (reg_equiv_invari...
mem_mode, insn, true, for_costs);
/* There exists at least one use of REGNO that cannot...
eliminated. Prevent the defining insn from being ...
reg_equiv_init (regno) = NULL;
if (!for_costs)
alter_reg (regno, -1, true);
}
return x;
-
--[[gcc-8.3/gcc/REGNO()]]
--[[gcc-8.3/gcc/reg_eliminate(global)]]
--[[gcc-8.3/gcc/plus_constant()]]
--[[gcc-8.3/gcc/reg_equiv_invariant()]]
--[[gcc-8.3/gcc/DEBUG_INSN_P()]]
--[[gcc-8.3/gcc/eliminate_regs_1()]]
--[[gcc-8.3/gcc/copy_rtx()]]
--[[gcc-8.3/gcc/reg_equiv_init()]]
--[[gcc-8.3/gcc/alter_reg()]]
/* You might think handling MINUS in a manner simila...
good idea. It is not. It has been tried multipl...
time the change has had to have been reverted.
Other parts of reload know a PLUS is special (gen...
and require special code to handle code a reloade...
Also consider backends where the flags register i...
MINUS, but we can emit a PLUS that does not clobb...
lea instruction comes to mind). If we try to rel...
may kill the flags register that was holding a us...
So, please before trying to handle MINUS, conside...
whole instead of this little section as well as t...
case PLUS:
/* If this is the sum of an eliminable register an...
the sum. */
if (REG_P (XEXP (x, 0))
&& REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
&& CONSTANT_P (XEXP (x, 1)))
{
for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIM...
ep++)
if (ep->from_rtx == XEXP (x, 0) && ep->can_eliminate)
{
/* The only time we want to replace a PLUS with a REG ...
occurs when the constant operand of the PLUS is the...
of the offset) is when we are inside a MEM. We won...
to do so at other times because that would change the
structure of the insn in a way that reload can't ha...
We special-case the commonest situation in
eliminate_regs_in_insn, so just replace a PLUS with a
PLUS here, unless inside a MEM. */
rtx _t;
if (mem_mode != 0
&& CONST_INT_P (XEXP (x, 1))
&& known_eq (INTVAL (XEXP (x, 1)), -ep->previous_o...
return ep->to_rtx;
else
return gen_rtx_PLUS (Pmode, ep->to_rtx,
plus_constant (Pmode, XEXP (x, 1),
ep->previous_offset));
}
}
/* If the register is not eliminable, we are done sin...
operand is a constant. */
return x;
}
-
--[[gcc-8.3/gcc/REGP()]]
--[[gcc-8.3/gcc/XEXP()]]
--[[gcc-8.3/gcc/REGNO()]]
--[[gcc-8.3/gcc/CONSTANT_P()]]
--[[gcc-8.3/gcc/reg_eliminate(global)]]
--[[gcc-8.3/gcc/CONST_INT_P()]]
--[[gcc-8.3/gcc/known_eq()]]
--[[gcc-8.3/gcc/INTVAL()]]
--[[gcc-8.3/gcc/gen_rtx_PLUS()]]
--[[gcc-8.3/gcc/plus_constant()]]
/* If this is part of an address, we want to bring...
outermost PLUS. We will do this by doing register rep...
our operands and seeing if a constant shows up in one ...
Note that there is no risk of modifying the structure ...
since we only get called for its operands, thus we are...
modifying the address inside a MEM, or something like ...
operand of a load-address insn. */
{
rtx new0 = eliminate_regs_1 (XEXP (x, 0), mem_mode, ins...
for_costs);
rtx new1 = eliminate_regs_1 (XEXP (x, 1), mem_mode, ins...
for_costs);
if (reg_renumber && (new0 != XEXP (x, 0) || new1 != XEX...
{
/* If one side is a PLUS and the other side is a ps...
didn't get a hard register but has a reg_equiv_c...
we must replace the constant here since it may n...
be in the position of any operand. */
if (GET_CODE (new0) == PLUS && REG_P (new1)
&& REGNO (new1) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[REGNO (new1)] < 0
&& reg_equivs
&& reg_equiv_constant (REGNO (new1)) != 0)
new1 = reg_equiv_constant (REGNO (new1));
else if (GET_CODE (new1) == PLUS && REG_P (new0)
&& REGNO (new0) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[REGNO (new0)] < 0
&& reg_equiv_constant (REGNO (new0)) != 0)
new0 = reg_equiv_constant (REGNO (new0));
new_rtx = form_sum (GET_MODE (x), new0, new1);
/* As above, if we are not inside a MEM we do not w...
turn a PLUS into something else. We might try t...
for an addition of 0 if we aren't optimizing. */
if (! mem_mode && GET_CODE (new_rtx) != PLUS)
return gen_rtx_PLUS (GET_MODE (x), new_rtx, const...
else
return new_rtx;
}
}
return x;
-
--[[gcc-8.3/gcc/XEXP()]]
--[[gcc-8.3/gcc/GET_CODE()]]
--[[gcc-8.3/gcc/REG_P()]]
--[[gcc-8.3/gcc/REGNO()]]
--[[gcc-8.3/gcc/reg_equiv_constant()]]
--[[gcc-8.3/gcc/form_sum()]]
--[[gcc-8.3/gcc/GET_MODE()]]
--[[gcc-8.3/gcc/gen_rtx_PLUS()]]
case MULT:
/* If this is the product of an eliminable registe...
constant, apply the distribute law and move the consta...
so that we have (plus (mult ..) ..). This is needed i...
to keep load-address insns valid. This case is patho...
We ignore the possibility of overflow here. */
if (REG_P (XEXP (x, 0))
&& REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
&& CONST_INT_P (XEXP (x, 1)))
for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMIN...
ep++)
if (ep->from_rtx == XEXP (x, 0) && ep->can_eliminate)
{
if (! mem_mode
/* Refs inside notes or in DEBUG_INSNs don't count for
this purpose. */
&& ! (insn != 0 && (GET_CODE (insn) == EXPR_LIST
|| GET_CODE (insn) == INSN_LIST
|| DEBUG_INSN_P (insn))))
ep->ref_outside_mem = 1;
return
plus_constant (Pmode,
gen_rtx_MULT (Pmode, ep->to_rtx, XEXP (x, 1)),
ep->previous_offset * INTVAL (XEXP (x, 1)));
}
-
--[[gcc-8.3/gcc/REG_P()]]
--[[gcc-8.3/gcc/REGNO()]]
--[[gcc-8.3/gcc/XEXP()]]
--[[gcc-8.3/gcc/CONST_INT_P()]]
--[[gcc-8.3/gcc/GET_CODE()]]
--[[gcc-8.3/gcc/DEBUG_INSN_P()]]
--[[gcc-8.3/gcc/plus_constant()]]
--[[gcc-8.3/gcc/gen_rtx_MULT()]]
--[[gcc-8.3/gcc/INTVAL()]]
/* fall through */
case CALL:
case COMPARE:
/* See comments before PLUS about handling MINUS. */
case MINUS:
case DIV: case UDIV:
case MOD: case UMOD:
case AND: case IOR: case XOR:
case ROTATERT: case ROTATE:
case ASHIFTRT: case LSHIFTRT: case ASHIFT:
case NE: case EQ:
case GE: case GT: case GEU: case GTU:
case LE: case LT: case LEU: case LTU:
{
rtx new0 = eliminate_regs_1 (XEXP (x, 0), mem_mode, ins...
for_costs);
rtx new1 = XEXP (x, 1)
? eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, false,
for_costs) : 0;
if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
return gen_rtx_fmt_ee (code, GET_MODE (x), new0, new1);
}
return x;
-
--[[gcc-8.3/gcc/eliminate_regs_1()]]
--[[gcc-8.3/gcc/XEXP()]]
--[[gcc-8.3/gcc/GET_MODE()]]
--[[gcc-8.3/gcc/gen_rtx_fmt_ee()]]
case EXPR_LIST:
/* If we have something in XEXP (x, 0), the usual ...
if (XEXP (x, 0))
{
new_rtx = eliminate_regs_1 (XEXP (x, 0), mem_mode, in...
for_costs);
if (new_rtx != XEXP (x, 0))
{
/* If this is a REG_DEAD note, it is not valid an...
Using the eliminated version could result in creating a
REG_DEAD note for the stack or frame pointer. */
if (REG_NOTE_KIND (x) == REG_DEAD)
return (XEXP (x, 1)
? eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true,
for_costs)
: NULL_RTX);
x = alloc_reg_note (REG_NOTE_KIND (x), new_rtx, X...
}
}
/* fall through */
-
--[[gcc-8.3/gcc/XEXP()]]
--[[gcc-8.3/gcc/eliminate_regs_1()]]
--[[gcc-8.3/gcc/REG_NOTE_KIND()]]
--[[gcc-8.3/gcc/alloc_reg_note()]]
case INSN_LIST:
case INT_LIST:
/* Now do eliminations in the rest of the chain. ...
an EXPR_LIST, this might result in allocating more mem...
strictly needed, but it simplifies the code. */
if (XEXP (x, 1))
{
new_rtx = eliminate_regs_1 (XEXP (x, 1), mem_mode, in...
for_costs);
if (new_rtx != XEXP (x, 1))
return
gen_rtx_fmt_ee (GET_CODE (x), GET_MODE (x), XEXP ...
}
return x;
-
--[[gcc-8.3/gcc/XEXP()]]
--[[gcc-8.3/gcc/eliminate_regs_1()]]
--[[gcc-8.3/gcc/gen_rtx_fmt_ee()]]
--[[gcc-8.3/gcc/GET_CODE()]]
case PRE_INC:
case POST_INC:
case PRE_DEC:
case POST_DEC:
/* We do not support elimination of a register tha...
elimination_effects has already make sure that this do...
happen. */
return x;
case PRE_MODIFY:
case POST_MODIFY:
/* We do not support elimination of a register tha...
elimination_effects has already make sure that this do...
happen. The only remaining case we need to consider h...
that the increment value may be an eliminable register...
if (GET_CODE (XEXP (x, 1)) == PLUS
&& XEXP (XEXP (x, 1), 0) == XEXP (x, 0))
{
rtx new_rtx = eliminate_regs_1 (XEXP (XEXP (x, 1), 1)...
insn, true, for_costs);
if (new_rtx != XEXP (XEXP (x, 1), 1))
return gen_rtx_fmt_ee (code, GET_MODE (x), XEXP (x,...
gen_rtx_PLUS (GET_MODE (x),
XEXP (x, 0), new_rtx));
}
return x;
-
--[[gcc-8.3/gcc/GET_CODE()]]
--[[gcc-8.3/gcc/XEXP()]]
--[[gcc-8.3/gcc/elieminate_regs_1()]]
--[[gcc-8.3/gcc/gen_rtx_fmt_ee()]]
--[[gcc-8.3/gcc/GET_MODE()]]
--[[gcc-8.3/gcc/gen_rtx_PLUS()]]
case STRICT_LOW_PART:
case NEG: case NOT:
case SIGN_EXTEND: case ZERO_EXTEND:
case TRUNCATE: case FLOAT_EXTEND: case FLOAT_TRU...
case FLOAT: case FIX:
case UNSIGNED_FIX: case UNSIGNED_FLOAT:
case ABS:
case SQRT:
case FFS:
case CLZ:
case CTZ:
case POPCOUNT:
case PARITY:
case BSWAP:
new_rtx = eliminate_regs_1 (XEXP (x, 0), mem_mode,...
for_costs);
if (new_rtx != XEXP (x, 0))
return gen_rtx_fmt_e (code, GET_MODE (x), new_rtx);
return x;
-
--[[gcc-8.3/gcc/eliminate_regs_1()]]
--[[gcc-8.3/gcc/XEXP()]]
--[[gcc-8.3/gcc/gen_rtx_fmt_e()]]
--[[gcc-8.3/gcc/GET_MODE()]]
case SUBREG:
/* Similar to above processing, but preserve SUBRE...
Convert (subreg (mem)) to (mem) if not paradoxical.
Also, if we have a non-paradoxical (subreg (pseudo)) a...
pseudo didn't get a hard reg, we must replace this wit...
eliminated version of the memory location because push...
may do the replacement in certain circumstances. */
if (REG_P (SUBREG_REG (x))
&& !paradoxical_subreg_p (x)
&& reg_equivs
&& reg_equiv_memory_loc (REGNO (SUBREG_REG (x))) != 0)
{
new_rtx = SUBREG_REG (x);
}
else
new_rtx = eliminate_regs_1 (SUBREG_REG (x), mem_mode, i...
-
--[[gcc-8.3/gcc/REG_P()]]
--[[gcc-8.3/gcc/SUBREG_REG()]]
--[[gcc-8.3/gcc/paradoxical_subreg_p()]]
--[[gcc-8.3/gcc/REGNO()]]
--[[gcc-8.3/gcc/reg_equiv_memory_loc()]]
--[[gcc-8.3/gcc/eliminate_regs_1()]]
if (new_rtx != SUBREG_REG (x))
{
poly_int64 x_size = GET_MODE_SIZE (GET_MODE (x));
poly_int64 new_size = GET_MODE_SIZE (GET_MODE (new_rt...
if (MEM_P (new_rtx)
&& ((partial_subreg_p (GET_MODE (x), GET_MODE (ne...
/* On RISC machines, combine can create rtl of the ...
(set (subreg:m1 (reg:m2 R) 0) ...)
where m1 < m2, and expects something interesting...
happen to the entire word. Moreover, it will us...
(reg:m2 R) later, expecting all bits to be prese...
So if the number of words is the same, preserve ...
subreg so that push_reload can see it. */
&& !(WORD_REGISTER_OPERATIONS
&& known_equal_after_align_down (x_size - 1,
new_size - 1,
UNITS_PER_WORD)))
|| known_eq (x_size, new_size))
)
return adjust_address_nv (new_rtx, GET_MODE (x), SU...
else if (insn && GET_CODE (insn) == DEBUG_INSN)
return gen_rtx_raw_SUBREG (GET_MODE (x), new_rtx, S...
else
return gen_rtx_SUBREG (GET_MODE (x), new_rtx, SUBRE...
}
return x;
-
--[[gcc-8.3/gcc/poly_int64]]
--[[gcc-8.3/gcc/GET_MODE_SIZE()]]
--[[gcc-8.3/gcc/GET_MODE()]]
--[[gcc-8.3/gcc/MEM_P()]]
--[[gcc-8.3/gcc/partial_subreg_p()]]
--[[gcc-8.3/gcc/known_equal_after_align_down()]]
--[[gcc-8.3/gcc/known_eq()]]
--[[gcc-8.3/gcc/adjust_address_nv()]]
--[[gcc-8.3/gcc/SUBREG_BYTE()]]
--[[gcc-8.3/gcc/gen_rtx_raw_SUBREG()]]
--[[gcc-8.3/gcc/gen_rtx_SUBREG()]]
case MEM:
/* Our only special processing is to pass the mode...
recursive call and copy the flags. While we are here,...
case more efficiently. */
new_rtx = eliminate_regs_1 (XEXP (x, 0), GET_MODE ...
for_costs);
if (for_costs
&& memory_address_p (GET_MODE (x), XEXP (x, 0))
&& !memory_address_p (GET_MODE (x), new_rtx))
note_reg_elim_costly (XEXP (x, 0), insn);
return replace_equiv_address_nv (x, new_rtx);
-
--[[gcc-8.3/gcc/eliminate_regs_1()]]
--[[gcc-8.3/gcc/XEXP()]]
--[[gcc-8.3/gcc/GET_MODE()]]
--[[gcc-8.3/gcc/memory_address_p()]]
--[[gcc-8.3/gcc/note_reg_elim_costly()]]
--[[gcc-8.3/gcc/replace_equiv_address_nv()]]
case USE:
/* Handle insn_list USE that a call to a pure func...
new_rtx = eliminate_regs_1 (XEXP (x, 0), VOIDmode,...
for_costs);
if (new_rtx != XEXP (x, 0))
return gen_rtx_USE (GET_MODE (x), new_rtx);
return x;
-
--[[gcc-8.3/gcc/eliminate_regs_1()]]
--[[gcc-8.3/gcc/XEXP()]]
--[[gcc-8.3/gcc/gen_rtx_USE()]]
--[[gcc-8.3/gcc/GET_MODE()]]
case CLOBBER:
case ASM_OPERANDS:
gcc_assert (insn && DEBUG_INSN_P (insn));
break;
-
--[[gcc-8.3/gcc/gcc_assert()]]
--[[gcc-8.3/gcc/DEBUG_INSN_P()]]
case SET:
gcc_unreachable ();
-
--[[gcc-8.3/gcc/gcc_unreachable()]]
default:
break;
}
/* Process each of our operands recursively. If any h...
copy of the rtx. */
fmt = GET_RTX_FORMAT (code);
for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
{
if (*fmt == 'e')
{
new_rtx = eliminate_regs_1 (XEXP (x, i), mem_mode, in...
for_costs);
if (new_rtx != XEXP (x, i) && ! copied)
{
x = shallow_copy_rtx (x);
copied = 1;
}
XEXP (x, i) = new_rtx;
}
-
--[[gcc-8.3/gcc/GET_RTX_FORMAT()]]
--[[gcc-8.3/gcc/GET_RTX_LENGTH()]]
--[[gcc-8.3/gcc/eliminate_regs_1()]]
--[[gcc-8.3/gcc/shallo_copy_rtx()]]
--[[gcc-8.3/gcc/XEXP()]]
else if (*fmt == 'E')
{
int copied_vec = 0;
for (j = 0; j < XVECLEN (x, i); j++)
{
new_rtx = eliminate_regs_1 (XVECEXP (x, i, j), me...
for_costs);
if (new_rtx != XVECEXP (x, i, j) && ! copied_vec)
{
rtvec new_v = gen_rtvec_v (XVECLEN (x, i),
XVEC (x, i)->elem);
if (! copied)
{
x = shallow_copy_rtx (x);
copied = 1;
}
XVEC (x, i) = new_v;
copied_vec = 1;
}
XVECEXP (x, i, j) = new_rtx;
}
}
-
--[[gcc-8.3/gcc/XVECLEN()]]
--[[gcc-8.3/gcc/eliminate_regs_1()]]
--[[gcc-8.3/gcc/XVECEXP()]]
--[[gcc-8.3/gcc/XVEC()]]
--[[gcc-8.3/gcc/gen_rtvec_v()]]
--[[gcc-8.3/gcc/shallow_copy_rtx()]]
}
return x;
}
*コメント [#q2d1c740]
ページ名: