Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
R
riscv-gcc-1
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
riscv-gcc-1
Commits
367b1cf5
Commit
367b1cf5
authored
Dec 21, 1999
by
Bernd Schmidt
Committed by
Bernd Schmidt
Dec 21, 1999
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Break up emit_reload_insns.
From-SVN: r31052
parent
ca098a1d
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
307 additions
and
263 deletions
+307
-263
gcc/ChangeLog
+12
-0
gcc/reload1.c
+295
-263
No files found.
gcc/ChangeLog
View file @
367b1cf5
1999
-
12
-
21
Bernd
Schmidt
<
bernds
@cygnus
.
co
.
uk
>
*
reload1
.
c
(
emit_reload_insns
)
:
Break
out
code
and
variables
into
...
(
input_reload_insns
,
other_input_address_reload_insns
,
other_input_reload_insns
,
input_address_reload_insns
,
inpaddr_address_reload_insns
,
output_reload_insns
,
output_address_reload_insns
,
outaddr_address_reload_insns
,
operand_reload_insns
,
other_operand_reload_insns
,
other_output_reload_insns
)
:
...
new
static
variables
,
and
...
(
emit_input_reload_insns
,
emit_output_reload_insns
,
do_input_reload
,
do_output_reload
)
:
...
new
functions
.
Tue
Dec
21
07
:
06
:
36
1999
Richard
Kenner
<
kenner
@vlsi1
.
ultra
.
nyu
.
edu
>
*
pa
.
h
(
FUNCTION_ARG_BOUNDARY
)
:
Never
return
0
.
...
...
gcc/reload1.c
View file @
367b1cf5
...
...
@@ -414,6 +414,14 @@ static int set_reload_reg PROTO((int, int));
static
void
choose_reload_regs_init
PROTO
((
struct
insn_chain
*
,
rtx
*
));
static
void
choose_reload_regs
PROTO
((
struct
insn_chain
*
));
static
void
merge_assigned_reloads
PROTO
((
rtx
));
static
void
emit_input_reload_insns
PROTO
((
struct
insn_chain
*
,
struct
reload
*
,
rtx
,
int
));
static
void
emit_output_reload_insns
PROTO
((
struct
insn_chain
*
,
struct
reload
*
,
int
));
static
void
do_input_reload
PROTO
((
struct
insn_chain
*
,
struct
reload
*
,
int
));
static
void
do_output_reload
PROTO
((
struct
insn_chain
*
,
struct
reload
*
,
int
));
static
void
emit_reload_insns
PROTO
((
struct
insn_chain
*
));
static
void
delete_output_reload
PROTO
((
rtx
,
int
,
int
));
static
void
delete_address_reloads
PROTO
((
rtx
,
rtx
));
...
...
@@ -5834,76 +5842,43 @@ merge_assigned_reloads (insn)
}
/* Output insns to reload values in and out of the chosen reload regs. */
/* These arrays are filled by emit_reload_insns and its subroutines. */
static
rtx
input_reload_insns
[
MAX_RECOG_OPERANDS
];
static
rtx
other_input_address_reload_insns
=
0
;
static
rtx
other_input_reload_insns
=
0
;
static
rtx
input_address_reload_insns
[
MAX_RECOG_OPERANDS
];
static
rtx
inpaddr_address_reload_insns
[
MAX_RECOG_OPERANDS
];
static
rtx
output_reload_insns
[
MAX_RECOG_OPERANDS
];
static
rtx
output_address_reload_insns
[
MAX_RECOG_OPERANDS
];
static
rtx
outaddr_address_reload_insns
[
MAX_RECOG_OPERANDS
];
static
rtx
operand_reload_insns
=
0
;
static
rtx
other_operand_reload_insns
=
0
;
static
rtx
other_output_reload_insns
[
MAX_RECOG_OPERANDS
];
/* Values to be put in spill_reg_store are put here first. */
static
rtx
new_spill_reg_store
[
FIRST_PSEUDO_REGISTER
];
static
HARD_REG_SET
reg_reloaded_died
;
/* Generate insns to perform reload RL, which is for the insn in CHAIN and
has the number J. OLD contains the value to be used as input. */
static
void
emit_
reload_insns
(
chain
)
emit_
input_reload_insns
(
chain
,
rl
,
old
,
j
)
struct
insn_chain
*
chain
;
struct
reload
*
rl
;
rtx
old
;
int
j
;
{
rtx
insn
=
chain
->
insn
;
register
int
j
;
rtx
input_reload_insns
[
MAX_RECOG_OPERANDS
];
rtx
other_input_address_reload_insns
=
0
;
rtx
other_input_reload_insns
=
0
;
rtx
input_address_reload_insns
[
MAX_RECOG_OPERANDS
];
rtx
inpaddr_address_reload_insns
[
MAX_RECOG_OPERANDS
];
rtx
output_reload_insns
[
MAX_RECOG_OPERANDS
];
rtx
output_address_reload_insns
[
MAX_RECOG_OPERANDS
];
rtx
outaddr_address_reload_insns
[
MAX_RECOG_OPERANDS
];
rtx
operand_reload_insns
=
0
;
rtx
other_operand_reload_insns
=
0
;
rtx
other_output_reload_insns
[
MAX_RECOG_OPERANDS
];
rtx
following_insn
=
NEXT_INSN
(
insn
);
rtx
before_insn
=
PREV_INSN
(
insn
);
int
special
;
/* Values to be put in spill_reg_store are put here first. */
rtx
new_spill_reg_store
[
FIRST_PSEUDO_REGISTER
];
HARD_REG_SET
reg_reloaded_died
;
CLEAR_HARD_REG_SET
(
reg_reloaded_died
);
for
(
j
=
0
;
j
<
reload_n_operands
;
j
++
)
input_reload_insns
[
j
]
=
input_address_reload_insns
[
j
]
=
inpaddr_address_reload_insns
[
j
]
=
output_reload_insns
[
j
]
=
output_address_reload_insns
[
j
]
=
outaddr_address_reload_insns
[
j
]
=
other_output_reload_insns
[
j
]
=
0
;
/* Now output the instructions to copy the data into and out of the
reload registers. Do these in the order that the reloads were reported,
since reloads of base and index registers precede reloads of operands
and the operands may need the base and index registers reloaded. */
for
(
j
=
0
;
j
<
n_reloads
;
j
++
)
{
register
rtx
old
;
register
rtx
reloadreg
=
rl
->
reg_rtx
;
rtx
oldequiv_reg
=
0
;
rtx
this_reload_insn
=
0
;
int
expect_occurrences
=
1
;
if
(
rld
[
j
].
reg_rtx
&&
REGNO
(
rld
[
j
].
reg_rtx
)
<
FIRST_PSEUDO_REGISTER
)
new_spill_reg_store
[
REGNO
(
rld
[
j
].
reg_rtx
)]
=
0
;
old
=
(
rld
[
j
].
in
&&
GET_CODE
(
rld
[
j
].
in
)
==
MEM
?
rld
[
j
].
in_reg
:
rld
[
j
].
in
);
if
(
old
!=
0
/* AUTO_INC reloads need to be handled even if inherited. We got an
AUTO_INC reload if reload_out is set but reload_out_reg isn't. */
&&
(
!
reload_inherited
[
j
]
||
(
rld
[
j
].
out
&&
!
rld
[
j
].
out_reg
))
&&
!
rtx_equal_p
(
rld
[
j
].
reg_rtx
,
old
)
&&
rld
[
j
].
reg_rtx
!=
0
)
{
register
rtx
reloadreg
=
rld
[
j
].
reg_rtx
;
rtx
oldequiv
=
0
;
int
special
=
0
;
enum
machine_mode
mode
;
rtx
*
where
;
/* Determine the mode to reload in.
This is very tricky because we have three to choose from.
There is the mode the insn operand wants (rld[J].
inmode).
There is the mode the insn operand wants (rl->
inmode).
There is the mode of the reload register RELOADREG.
There is the intrinsic mode of the operand, which we could find
by stripping some SUBREGs.
...
...
@@ -5935,7 +5910,7 @@ emit_reload_insns (chain)
mode
=
GET_MODE
(
old
);
if
(
mode
==
VOIDmode
)
mode
=
rld
[
j
].
inmode
;
mode
=
rl
->
inmode
;
#ifdef SECONDARY_INPUT_RELOAD_CLASS
/* If we need a secondary register for this operation, see if
...
...
@@ -5943,12 +5918,12 @@ emit_reload_insns (chain)
do this if the secondary register will be used as a scratch
register. */
if
(
rld
[
j
].
secondary_in_reload
>=
0
&&
rld
[
j
].
secondary_in_icode
==
CODE_FOR_nothing
if
(
rl
->
secondary_in_reload
>=
0
&&
rl
->
secondary_in_icode
==
CODE_FOR_nothing
&&
optimize
)
oldequiv
=
find_equiv_reg
(
old
,
insn
,
rld
[
rld
[
j
].
secondary_in_reload
].
class
,
rld
[
rl
->
secondary_in_reload
].
class
,
-
1
,
NULL_PTR
,
0
,
mode
);
#endif
...
...
@@ -5974,9 +5949,9 @@ emit_reload_insns (chain)
/* Don't use OLDEQUIV if any other reload changes it at an
earlier stage of this insn or at this stage. */
if
(
!
reload_reg_free_for_value_p
(
regno
,
rld
[
j
].
opnum
,
rld
[
j
].
when_needed
,
rld
[
j
].
in
,
const0_rtx
,
j
,
if
(
!
reload_reg_free_for_value_p
(
regno
,
rl
->
opnum
,
rl
->
when_needed
,
rl
->
in
,
const0_rtx
,
j
,
0
))
oldequiv
=
0
;
...
...
@@ -5986,18 +5961,18 @@ emit_reload_insns (chain)
or memory. */
if
(
oldequiv
!=
0
&&
((
REGNO_REG_CLASS
(
regno
)
!=
rld
[
j
].
class
&&
((
REGNO_REG_CLASS
(
regno
)
!=
rl
->
class
&&
(
REGISTER_MOVE_COST
(
REGNO_REG_CLASS
(
regno
),
rld
[
j
].
class
)
>=
MEMORY_MOVE_COST
(
mode
,
rld
[
j
].
class
,
1
)))
rl
->
class
)
>=
MEMORY_MOVE_COST
(
mode
,
rl
->
class
,
1
)))
#ifdef SECONDARY_INPUT_RELOAD_CLASS
||
(
SECONDARY_INPUT_RELOAD_CLASS
(
rld
[
j
].
class
,
||
(
SECONDARY_INPUT_RELOAD_CLASS
(
rl
->
class
,
mode
,
oldequiv
)
!=
NO_REGS
)
#endif
#ifdef SECONDARY_MEMORY_NEEDED
||
SECONDARY_MEMORY_NEEDED
(
REGNO_REG_CLASS
(
regno
),
rld
[
j
].
class
,
rl
->
class
,
mode
)
#endif
))
...
...
@@ -6010,10 +5985,10 @@ emit_reload_insns (chain)
find the pseudo in RELOAD_IN_REG. */
if
(
oldequiv
==
0
&&
reload_override_in
[
j
]
&&
GET_CODE
(
rld
[
j
].
in_reg
)
==
REG
)
&&
GET_CODE
(
rl
->
in_reg
)
==
REG
)
{
oldequiv
=
old
;
old
=
rld
[
j
].
in_reg
;
old
=
rl
->
in_reg
;
}
if
(
oldequiv
==
0
)
oldequiv
=
old
;
...
...
@@ -6032,7 +6007,7 @@ emit_reload_insns (chain)
&&
GET_CODE
(
old
)
==
REG
&&
(
dead_or_set_p
(
insn
,
spill_reg_stored_to
[
REGNO
(
oldequiv
)])
||
rtx_equal_p
(
spill_reg_stored_to
[
REGNO
(
oldequiv
)],
rld
[
j
].
out_reg
)))
rl
->
out_reg
)))
delete_output_reload
(
insn
,
j
,
REGNO
(
oldequiv
));
/* Encapsulate both RELOADREG and OLDEQUIV into that mode,
...
...
@@ -6050,25 +6025,25 @@ emit_reload_insns (chain)
oldequiv
=
gen_rtx_SUBREG
(
mode
,
oldequiv
,
0
);
/* Switch to the right place to emit the reload insns. */
switch
(
rld
[
j
].
when_needed
)
switch
(
rl
->
when_needed
)
{
case
RELOAD_OTHER
:
where
=
&
other_input_reload_insns
;
break
;
case
RELOAD_FOR_INPUT
:
where
=
&
input_reload_insns
[
rld
[
j
].
opnum
];
where
=
&
input_reload_insns
[
rl
->
opnum
];
break
;
case
RELOAD_FOR_INPUT_ADDRESS
:
where
=
&
input_address_reload_insns
[
rld
[
j
].
opnum
];
where
=
&
input_address_reload_insns
[
rl
->
opnum
];
break
;
case
RELOAD_FOR_INPADDR_ADDRESS
:
where
=
&
inpaddr_address_reload_insns
[
rld
[
j
].
opnum
];
where
=
&
inpaddr_address_reload_insns
[
rl
->
opnum
];
break
;
case
RELOAD_FOR_OUTPUT_ADDRESS
:
where
=
&
output_address_reload_insns
[
rld
[
j
].
opnum
];
where
=
&
output_address_reload_insns
[
rl
->
opnum
];
break
;
case
RELOAD_FOR_OUTADDR_ADDRESS
:
where
=
&
outaddr_address_reload_insns
[
rld
[
j
].
opnum
];
where
=
&
outaddr_address_reload_insns
[
rl
->
opnum
];
break
;
case
RELOAD_FOR_OPERAND_ADDRESS
:
where
=
&
operand_reload_insns
;
...
...
@@ -6084,21 +6059,20 @@ emit_reload_insns (chain)
}
push_to_sequence
(
*
where
);
special
=
0
;
/* Auto-increment addresses must be reloaded in a special way. */
if
(
rld
[
j
].
out
&&
!
rld
[
j
].
out_reg
)
if
(
rl
->
out
&&
!
rl
->
out_reg
)
{
/* We are not going to bother supporting the case where a
incremented register can't be copied directly from
OLDEQUIV since this seems highly unlikely. */
if
(
rld
[
j
].
secondary_in_reload
>=
0
)
if
(
rl
->
secondary_in_reload
>=
0
)
abort
();
if
(
reload_inherited
[
j
])
oldequiv
=
reloadreg
;
old
=
XEXP
(
rld
[
j
].
in_reg
,
0
);
old
=
XEXP
(
rl
->
in_reg
,
0
);
if
(
optimize
&&
GET_CODE
(
oldequiv
)
==
REG
&&
REGNO
(
oldequiv
)
<
FIRST_PSEUDO_REGISTER
...
...
@@ -6114,8 +6088,8 @@ emit_reload_insns (chain)
special
=
1
;
/* Output a special code sequence for this case. */
new_spill_reg_store
[
REGNO
(
reloadreg
)]
=
inc_for_reload
(
reloadreg
,
oldequiv
,
rld
[
j
].
out
,
rld
[
j
].
inc
);
=
inc_for_reload
(
reloadreg
,
oldequiv
,
rl
->
out
,
rl
->
inc
);
}
/* If we are reloading a pseudo-register that was set by the previous
...
...
@@ -6128,9 +6102,9 @@ emit_reload_insns (chain)
/* This is unsafe if some other reload
uses the same reg first. */
&&
reload_reg_free_for_value_p
(
REGNO
(
reloadreg
),
rld
[
j
].
opnum
,
rld
[
j
].
when_needed
,
old
,
rld
[
j
].
out
,
rl
->
opnum
,
rl
->
when_needed
,
old
,
rl
->
out
,
j
,
0
))
{
rtx
temp
=
PREV_INSN
(
insn
);
...
...
@@ -6170,21 +6144,16 @@ emit_reload_insns (chain)
if
(
REG_N_DEATHS
(
REGNO
(
old
))
==
1
&&
REG_N_SETS
(
REGNO
(
old
))
==
1
)
{
reg_renumber
[
REGNO
(
old
)]
=
REGNO
(
rld
[
j
].
reg_rtx
);
reg_renumber
[
REGNO
(
old
)]
=
REGNO
(
rl
->
reg_rtx
);
alter_reg
(
REGNO
(
old
),
-
1
);
}
special
=
1
;
return
;
}
}
/* We can't do that, so output an insn to load RELOADREG. */
if
(
!
special
)
{
#ifdef SECONDARY_INPUT_RELOAD_CLASS
rtx
second_reload_reg
=
0
;
enum
insn_code
icode
;
/* If we have a secondary reload, pick up the secondary register
and icode, if any. If OLDEQUIV and OLD are different or
if this is an in-out reload, recompute whether or not we
...
...
@@ -6196,12 +6165,14 @@ emit_reload_insns (chain)
because we don't make such reloads when both the input and
output need secondary reload registers. */
if
(
rld
[
j
].
secondary_in_reload
>=
0
)
if
(
rl
->
secondary_in_reload
>=
0
)
{
int
secondary_reload
=
rld
[
j
].
secondary_in_reload
;
rtx
second_reload_reg
=
0
;
int
secondary_reload
=
rl
->
secondary_in_reload
;
rtx
real_oldequiv
=
oldequiv
;
rtx
real_old
=
old
;
rtx
tmp
;
enum
insn_code
icode
;
/* If OLDEQUIV is a pseudo with a MEM, get the real MEM
and similarly for OLD.
...
...
@@ -6227,7 +6198,7 @@ emit_reload_insns (chain)
if
(
!
reg_equiv_mem
[
REGNO
(
tmp
)]
||
num_not_at_initial_offset
||
GET_CODE
(
oldequiv
)
==
SUBREG
)
real_oldequiv
=
rld
[
j
].
in
;
real_oldequiv
=
rl
->
in
;
else
real_oldequiv
=
reg_equiv_mem
[
REGNO
(
tmp
)];
}
...
...
@@ -6243,19 +6214,19 @@ emit_reload_insns (chain)
if
(
!
reg_equiv_mem
[
REGNO
(
tmp
)]
||
num_not_at_initial_offset
||
GET_CODE
(
old
)
==
SUBREG
)
real_old
=
rld
[
j
].
in
;
real_old
=
rl
->
in
;
else
real_old
=
reg_equiv_mem
[
REGNO
(
tmp
)];
}
second_reload_reg
=
rld
[
secondary_reload
].
reg_rtx
;
icode
=
rld
[
j
].
secondary_in_icode
;
icode
=
rl
->
secondary_in_icode
;
if
((
old
!=
oldequiv
&&
!
rtx_equal_p
(
old
,
oldequiv
))
||
(
rld
[
j
].
in
!=
0
&&
rld
[
j
].
out
!=
0
))
||
(
rl
->
in
!=
0
&&
rl
->
out
!=
0
))
{
enum
reg_class
new_class
=
SECONDARY_INPUT_RELOAD_CLASS
(
rld
[
j
].
class
,
=
SECONDARY_INPUT_RELOAD_CLASS
(
rl
->
class
,
mode
,
real_oldequiv
);
if
(
new_class
==
NO_REGS
)
...
...
@@ -6312,7 +6283,7 @@ emit_reload_insns (chain)
{
emit_insn
(
GEN_FCN
(
icode
)
(
reloadreg
,
real_oldequiv
,
second_reload_reg
));
special
=
1
;
return
;
}
else
{
...
...
@@ -6332,8 +6303,8 @@ emit_reload_insns (chain)
}
else
gen_reload
(
second_reload_reg
,
real_oldequiv
,
rld
[
j
].
opnum
,
rld
[
j
].
when_needed
);
rl
->
opnum
,
rl
->
when_needed
);
oldequiv
=
second_reload_reg
;
}
...
...
@@ -6341,7 +6312,7 @@ emit_reload_insns (chain)
}
#endif
if
(
!
special
&&
!
rtx_equal_p
(
reloadreg
,
oldequiv
))
if
(
!
rtx_equal_p
(
reloadreg
,
oldequiv
))
{
rtx
real_oldequiv
=
oldequiv
;
...
...
@@ -6357,14 +6328,11 @@ emit_reload_insns (chain)
[
REGNO
(
SUBREG_REG
(
oldequiv
))]
!=
0
)
||
(
reg_equiv_constant
[
REGNO
(
SUBREG_REG
(
oldequiv
))]
!=
0
))))
real_oldequiv
=
rld
[
j
].
in
;
gen_reload
(
reloadreg
,
real_oldequiv
,
rld
[
j
].
opnum
,
rld
[
j
].
when_needed
);
real_oldequiv
=
rl
->
in
;
gen_reload
(
reloadreg
,
real_oldequiv
,
rl
->
opnum
,
rl
->
when_needed
);
}
}
this_reload_insn
=
get_last_insn
();
/* End this sequence. */
*
where
=
get_insns
();
end_sequence
();
...
...
@@ -6373,142 +6341,31 @@ emit_reload_insns (chain)
can see the actual register usage. */
if
(
oldequiv_reg
)
reload_override_in
[
j
]
=
oldequiv
;
}
/* When inheriting a wider reload, we have a MEM in rld[j].in,
e.g. inheriting a SImode output reload for
(mem:HI (plus:SI (reg:SI 14 fp) (const_int 10))) */
if
(
optimize
&&
reload_inherited
[
j
]
&&
rld
[
j
].
in
&&
GET_CODE
(
rld
[
j
].
in
)
==
MEM
&&
GET_CODE
(
rld
[
j
].
in_reg
)
==
MEM
&&
reload_spill_index
[
j
]
>=
0
&&
TEST_HARD_REG_BIT
(
reg_reloaded_valid
,
reload_spill_index
[
j
]))
{
expect_occurrences
=
count_occurrences
(
PATTERN
(
insn
),
rld
[
j
].
in
)
==
1
?
0
:
-
1
;
rld
[
j
].
in
=
regno_reg_rtx
[
reg_reloaded_contents
[
reload_spill_index
[
j
]]];
}
/* If we are reloading a register that was recently stored in with an
output-reload, see if we can prove there was
actually no need to store the old value in it. */
if
(
optimize
&&
(
reload_inherited
[
j
]
||
reload_override_in
[
j
])
&&
rld
[
j
].
reg_rtx
&&
GET_CODE
(
rld
[
j
].
reg_rtx
)
==
REG
&&
spill_reg_store
[
REGNO
(
rld
[
j
].
reg_rtx
)]
!=
0
#if 0
/* There doesn't seem to be any reason to restrict this to pseudos
and doing so loses in the case where we are copying from a
register of the wrong class. */
&& (REGNO (spill_reg_stored_to[REGNO (rld[j].reg_rtx)])
>= FIRST_PSEUDO_REGISTER)
#endif
/* The insn might have already some references to stackslots
replaced by MEMs, while reload_out_reg still names the
original pseudo. */
&&
(
dead_or_set_p
(
insn
,
spill_reg_stored_to
[
REGNO
(
rld
[
j
].
reg_rtx
)])
||
rtx_equal_p
(
spill_reg_stored_to
[
REGNO
(
rld
[
j
].
reg_rtx
)],
rld
[
j
].
out_reg
)))
delete_output_reload
(
insn
,
j
,
REGNO
(
rld
[
j
].
reg_rtx
));
/* Input-reloading is done. Now do output-reloading,
storing the value from the reload-register after the main insn
if rld[j].out is nonzero.
??? At some point we need to support handling output reloads of
JUMP_INSNs or insns that set cc0. */
/* If this is an output reload that stores something that is
not loaded in this same reload, see if we can eliminate a previous
store. */
{
rtx
pseudo
=
rld
[
j
].
out_reg
;
if
(
pseudo
&&
GET_CODE
(
pseudo
)
==
REG
&&
!
rtx_equal_p
(
rld
[
j
].
in_reg
,
pseudo
)
&&
REGNO
(
pseudo
)
>=
FIRST_PSEUDO_REGISTER
&&
reg_last_reload_reg
[
REGNO
(
pseudo
)])
{
int
pseudo_no
=
REGNO
(
pseudo
);
int
last_regno
=
REGNO
(
reg_last_reload_reg
[
pseudo_no
]);
/* We don't need to test full validity of last_regno for
inherit here; we only want to know if the store actually
matches the pseudo. */
if
(
reg_reloaded_contents
[
last_regno
]
==
pseudo_no
&&
spill_reg_store
[
last_regno
]
&&
rtx_equal_p
(
pseudo
,
spill_reg_stored_to
[
last_regno
]))
delete_output_reload
(
insn
,
j
,
last_regno
);
}
}
}
old
=
rld
[
j
].
out_reg
;
if
(
old
!=
0
&&
rld
[
j
].
reg_rtx
!=
old
&&
rld
[
j
].
reg_rtx
!=
0
)
{
register
rtx
reloadreg
=
rld
[
j
].
reg_rtx
;
#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
register
rtx
second_reloadreg
=
0
;
#endif
rtx
note
,
p
;
enum
machine_mode
mode
;
/* Generate insns to for the output reload RL, which is for the insn described
by CHAIN and has the number J. */
static
void
emit_output_reload_insns
(
chain
,
rl
,
j
)
struct
insn_chain
*
chain
;
struct
reload
*
rl
;
int
j
;
{
rtx
reloadreg
=
rl
->
reg_rtx
;
rtx
insn
=
chain
->
insn
;
int
special
=
0
;
rtx
old
=
rl
->
out
;
enum
machine_mode
mode
=
GET_MODE
(
old
);
rtx
p
;
/* An output operand that dies right away does need a reload,
but need not be copied from it. Show the new location in the
REG_UNUSED note. */
if
((
GET_CODE
(
old
)
==
REG
||
GET_CODE
(
old
)
==
SCRATCH
)
&&
(
note
=
find_reg_note
(
insn
,
REG_UNUSED
,
old
))
!=
0
)
{
XEXP
(
note
,
0
)
=
rld
[
j
].
reg_rtx
;
continue
;
}
/* Likewise for a SUBREG of an operand that dies. */
else
if
(
GET_CODE
(
old
)
==
SUBREG
&&
GET_CODE
(
SUBREG_REG
(
old
))
==
REG
&&
0
!=
(
note
=
find_reg_note
(
insn
,
REG_UNUSED
,
SUBREG_REG
(
old
))))
{
XEXP
(
note
,
0
)
=
gen_lowpart_common
(
GET_MODE
(
old
),
rld
[
j
].
reg_rtx
);
continue
;
}
else
if
(
GET_CODE
(
old
)
==
SCRATCH
)
/* If we aren't optimizing, there won't be a REG_UNUSED note,
but we don't want to make an output reload. */
continue
;
#if 0
/* Strip off of OLD any size-increasing SUBREGs such as
(SUBREG:SI foo:QI 0). */
while (GET_CODE (old) == SUBREG && SUBREG_WORD (old) == 0
&& (GET_MODE_SIZE (GET_MODE (old))
> GET_MODE_SIZE (GET_MODE (SUBREG_REG (old)))))
old = SUBREG_REG (old);
#endif
/* If is a JUMP_INSN, we can't support output reloads yet. */
if
(
GET_CODE
(
insn
)
==
JUMP_INSN
)
abort
();
if
(
rld
[
j
].
when_needed
==
RELOAD_OTHER
)
if
(
rl
->
when_needed
==
RELOAD_OTHER
)
start_sequence
();
else
push_to_sequence
(
output_reload_insns
[
rld
[
j
].
opnum
]);
old
=
rld
[
j
].
out
;
push_to_sequence
(
output_reload_insns
[
rl
->
opnum
]);
/* Determine the mode to reload in.
See comments above (for input reloading). */
mode
=
GET_MODE
(
old
);
if
(
mode
==
VOIDmode
)
{
/* VOIDmode should never happen for an output. */
...
...
@@ -6530,7 +6387,7 @@ emit_reload_insns (chain)
one, since it will be stored into OLD. We might need a secondary
register only for an input reload, so check again here. */
if
(
rld
[
j
].
secondary_out_reload
>=
0
)
if
(
rl
->
secondary_out_reload
>=
0
)
{
rtx
real_old
=
old
;
...
...
@@ -6538,18 +6395,18 @@ emit_reload_insns (chain)
&&
reg_equiv_mem
[
REGNO
(
old
)]
!=
0
)
real_old
=
reg_equiv_mem
[
REGNO
(
old
)];
if
((
SECONDARY_OUTPUT_RELOAD_CLASS
(
rld
[
j
].
class
,
if
((
SECONDARY_OUTPUT_RELOAD_CLASS
(
rl
->
class
,
mode
,
real_old
)
!=
NO_REGS
))
{
second_reloadreg
=
reloadreg
;
reloadreg
=
rld
[
rld
[
j
].
secondary_out_reload
].
reg_rtx
;
rtx
second_reloadreg
=
reloadreg
;
reloadreg
=
rld
[
rl
->
secondary_out_reload
].
reg_rtx
;
/* See if RELOADREG is to be used as a scratch register
or as an intermediate register. */
if
(
rld
[
j
].
secondary_out_icode
!=
CODE_FOR_nothing
)
if
(
rl
->
secondary_out_icode
!=
CODE_FOR_nothing
)
{
emit_insn
((
GEN_FCN
(
rld
[
j
].
secondary_out_icode
)
emit_insn
((
GEN_FCN
(
rl
->
secondary_out_icode
)
(
real_old
,
second_reloadreg
,
reloadreg
)));
special
=
1
;
}
...
...
@@ -6558,7 +6415,7 @@ emit_reload_insns (chain)
/* See if we need both a scratch and intermediate reload
register. */
int
secondary_reload
=
rld
[
j
].
secondary_out_reload
;
int
secondary_reload
=
rl
->
secondary_out_reload
;
enum
insn_code
tertiary_icode
=
rld
[
secondary_reload
].
secondary_out_icode
;
...
...
@@ -6587,7 +6444,7 @@ emit_reload_insns (chain)
real_old
=
SUBREG_REG
(
real_old
),
reloadreg
=
tem
;
gen_reload
(
reloadreg
,
second_reloadreg
,
rld
[
j
].
opnum
,
rld
[
j
].
when_needed
);
rl
->
opnum
,
rl
->
when_needed
);
emit_insn
((
GEN_FCN
(
tertiary_icode
)
(
real_old
,
reloadreg
,
third_reloadreg
)));
special
=
1
;
...
...
@@ -6598,7 +6455,7 @@ emit_reload_insns (chain)
OUT later. */
gen_reload
(
reloadreg
,
second_reloadreg
,
rld
[
j
].
opnum
,
rld
[
j
].
when_needed
);
rl
->
opnum
,
rl
->
when_needed
);
}
}
}
...
...
@@ -6617,8 +6474,8 @@ emit_reload_insns (chain)
||
rtx_equal_p
(
old
,
SET_DEST
(
set
))
||
!
reg_mentioned_p
(
old
,
SET_SRC
(
set
))
||
!
regno_clobbered_p
(
REGNO
(
old
),
insn
))
gen_reload
(
old
,
reloadreg
,
rld
[
j
].
opnum
,
rld
[
j
].
when_needed
);
gen_reload
(
old
,
reloadreg
,
rl
->
opnum
,
rl
->
when_needed
);
}
/* Look at all insns we emitted, just to be safe. */
...
...
@@ -6633,12 +6490,12 @@ emit_reload_insns (chain)
reg_has_output_reload will make this do nothing. */
note_stores
(
pat
,
forget_old_reloads_1
,
NULL
);
if
(
reg_mentioned_p
(
rld
[
j
].
reg_rtx
,
pat
))
if
(
reg_mentioned_p
(
rl
->
reg_rtx
,
pat
))
{
rtx
set
=
single_set
(
insn
);
if
(
reload_spill_index
[
j
]
<
0
&&
set
&&
SET_SRC
(
set
)
==
rld
[
j
].
reg_rtx
)
&&
SET_SRC
(
set
)
==
rl
->
reg_rtx
)
{
int
src
=
REGNO
(
SET_SRC
(
set
));
...
...
@@ -6647,9 +6504,9 @@ emit_reload_insns (chain)
if
(
find_regno_note
(
insn
,
REG_DEAD
,
src
))
SET_HARD_REG_BIT
(
reg_reloaded_died
,
src
);
}
if
(
REGNO
(
rld
[
j
].
reg_rtx
)
<
FIRST_PSEUDO_REGISTER
)
if
(
REGNO
(
rl
->
reg_rtx
)
<
FIRST_PSEUDO_REGISTER
)
{
int
s
=
rld
[
j
].
secondary_out_reload
;
int
s
=
rl
->
secondary_out_reload
;
set
=
single_set
(
p
);
/* If this reload copies only to the secondary reload
register, the secondary reload does the actual
...
...
@@ -6659,7 +6516,7 @@ emit_reload_insns (chain)
has and where the actual store to the pseudo is
made; leave new_spill_reg_store alone. */
else
if
(
s
>=
0
&&
SET_SRC
(
set
)
==
rld
[
j
].
reg_rtx
&&
SET_SRC
(
set
)
==
rl
->
reg_rtx
&&
SET_DEST
(
set
)
==
rld
[
s
].
reg_rtx
)
{
/* Usually the next instruction will be the
...
...
@@ -6668,8 +6525,8 @@ emit_reload_insns (chain)
that insn will allow an extra optimization. */
rtx
s_reg
=
rld
[
s
].
reg_rtx
;
rtx
next
=
NEXT_INSN
(
p
);
rld
[
s
].
out
=
rld
[
j
].
out
;
rld
[
s
].
out_reg
=
rld
[
j
].
out_reg
;
rld
[
s
].
out
=
rl
->
out
;
rld
[
s
].
out_reg
=
rl
->
out_reg
;
set
=
single_set
(
next
);
if
(
set
&&
SET_SRC
(
set
)
==
s_reg
&&
!
new_spill_reg_store
[
REGNO
(
s_reg
)])
...
...
@@ -6680,21 +6537,196 @@ emit_reload_insns (chain)
}
}
else
new_spill_reg_store
[
REGNO
(
rld
[
j
].
reg_rtx
)]
=
p
;
new_spill_reg_store
[
REGNO
(
rl
->
reg_rtx
)]
=
p
;
}
}
}
if
(
rld
[
j
].
when_needed
==
RELOAD_OTHER
)
if
(
rl
->
when_needed
==
RELOAD_OTHER
)
{
emit_insns
(
other_output_reload_insns
[
rld
[
j
].
opnum
]);
other_output_reload_insns
[
rld
[
j
].
opnum
]
=
get_insns
();
emit_insns
(
other_output_reload_insns
[
rl
->
opnum
]);
other_output_reload_insns
[
rl
->
opnum
]
=
get_insns
();
}
else
output_reload_insns
[
rld
[
j
].
opnum
]
=
get_insns
();
output_reload_insns
[
rl
->
opnum
]
=
get_insns
();
end_sequence
();
}
/* Do input reloading for reload RL, which is for the insn described by CHAIN
and has the number J. */
static
void
do_input_reload
(
chain
,
rl
,
j
)
struct
insn_chain
*
chain
;
struct
reload
*
rl
;
int
j
;
{
int
expect_occurrences
=
1
;
rtx
insn
=
chain
->
insn
;
rtx
old
=
(
rl
->
in
&&
GET_CODE
(
rl
->
in
)
==
MEM
?
rl
->
in_reg
:
rl
->
in
);
if
(
old
!=
0
/* AUTO_INC reloads need to be handled even if inherited. We got an
AUTO_INC reload if reload_out is set but reload_out_reg isn't. */
&&
(
!
reload_inherited
[
j
]
||
(
rl
->
out
&&
!
rl
->
out_reg
))
&&
!
rtx_equal_p
(
rl
->
reg_rtx
,
old
)
&&
rl
->
reg_rtx
!=
0
)
{
emit_input_reload_insns
(
chain
,
rld
+
j
,
old
,
j
);
}
/* When inheriting a wider reload, we have a MEM in rl->in,
e.g. inheriting a SImode output reload for
(mem:HI (plus:SI (reg:SI 14 fp) (const_int 10))) */
if
(
optimize
&&
reload_inherited
[
j
]
&&
rl
->
in
&&
GET_CODE
(
rl
->
in
)
==
MEM
&&
GET_CODE
(
rl
->
in_reg
)
==
MEM
&&
reload_spill_index
[
j
]
>=
0
&&
TEST_HARD_REG_BIT
(
reg_reloaded_valid
,
reload_spill_index
[
j
]))
{
expect_occurrences
=
count_occurrences
(
PATTERN
(
insn
),
rl
->
in
)
==
1
?
0
:
-
1
;
rl
->
in
=
regno_reg_rtx
[
reg_reloaded_contents
[
reload_spill_index
[
j
]]];
}
/* If we are reloading a register that was recently stored in with an
output-reload, see if we can prove there was
actually no need to store the old value in it. */
if
(
optimize
&&
(
reload_inherited
[
j
]
||
reload_override_in
[
j
])
&&
rl
->
reg_rtx
&&
GET_CODE
(
rl
->
reg_rtx
)
==
REG
&&
spill_reg_store
[
REGNO
(
rl
->
reg_rtx
)]
!=
0
#if 0
/* There doesn't seem to be any reason to restrict this to pseudos
and doing so loses in the case where we are copying from a
register of the wrong class. */
&& (REGNO (spill_reg_stored_to[REGNO (rl->reg_rtx)])
>= FIRST_PSEUDO_REGISTER)
#endif
/* The insn might have already some references to stackslots
replaced by MEMs, while reload_out_reg still names the
original pseudo. */
&&
(
dead_or_set_p
(
insn
,
spill_reg_stored_to
[
REGNO
(
rl
->
reg_rtx
)])
||
rtx_equal_p
(
spill_reg_stored_to
[
REGNO
(
rl
->
reg_rtx
)],
rl
->
out_reg
)))
delete_output_reload
(
insn
,
j
,
REGNO
(
rl
->
reg_rtx
));
}
/* Do output reloading for reload RL, which is for the insn described by
CHAIN and has the number J.
??? At some point we need to support handling output reloads of
JUMP_INSNs or insns that set cc0. */
static
void
do_output_reload
(
chain
,
rl
,
j
)
struct
insn_chain
*
chain
;
struct
reload
*
rl
;
int
j
;
{
rtx
note
,
old
;
rtx
insn
=
chain
->
insn
;
/* If this is an output reload that stores something that is
not loaded in this same reload, see if we can eliminate a previous
store. */
rtx
pseudo
=
rl
->
out_reg
;
if
(
pseudo
&&
GET_CODE
(
pseudo
)
==
REG
&&
!
rtx_equal_p
(
rl
->
in_reg
,
pseudo
)
&&
REGNO
(
pseudo
)
>=
FIRST_PSEUDO_REGISTER
&&
reg_last_reload_reg
[
REGNO
(
pseudo
)])
{
int
pseudo_no
=
REGNO
(
pseudo
);
int
last_regno
=
REGNO
(
reg_last_reload_reg
[
pseudo_no
]);
/* We don't need to test full validity of last_regno for
inherit here; we only want to know if the store actually
matches the pseudo. */
if
(
reg_reloaded_contents
[
last_regno
]
==
pseudo_no
&&
spill_reg_store
[
last_regno
]
&&
rtx_equal_p
(
pseudo
,
spill_reg_stored_to
[
last_regno
]))
delete_output_reload
(
insn
,
j
,
last_regno
);
}
old
=
rl
->
out_reg
;
if
(
old
==
0
||
rl
->
reg_rtx
==
old
||
rl
->
reg_rtx
==
0
)
return
;
/* An output operand that dies right away does need a reload,
but need not be copied from it. Show the new location in the
REG_UNUSED note. */
if
((
GET_CODE
(
old
)
==
REG
||
GET_CODE
(
old
)
==
SCRATCH
)
&&
(
note
=
find_reg_note
(
insn
,
REG_UNUSED
,
old
))
!=
0
)
{
XEXP
(
note
,
0
)
=
rl
->
reg_rtx
;
return
;
}
/* Likewise for a SUBREG of an operand that dies. */
else
if
(
GET_CODE
(
old
)
==
SUBREG
&&
GET_CODE
(
SUBREG_REG
(
old
))
==
REG
&&
0
!=
(
note
=
find_reg_note
(
insn
,
REG_UNUSED
,
SUBREG_REG
(
old
))))
{
XEXP
(
note
,
0
)
=
gen_lowpart_common
(
GET_MODE
(
old
),
rl
->
reg_rtx
);
return
;
}
else
if
(
GET_CODE
(
old
)
==
SCRATCH
)
/* If we aren't optimizing, there won't be a REG_UNUSED note,
but we don't want to make an output reload. */
return
;
/* If is a JUMP_INSN, we can't support output reloads yet. */
if
(
GET_CODE
(
insn
)
==
JUMP_INSN
)
abort
();
emit_output_reload_insns
(
chain
,
rld
+
j
,
j
);
}
/* Output insns to reload values in and out of the chosen reload regs. */
static
void
emit_reload_insns
(
chain
)
struct
insn_chain
*
chain
;
{
rtx
insn
=
chain
->
insn
;
register
int
j
;
rtx
following_insn
=
NEXT_INSN
(
insn
);
rtx
before_insn
=
PREV_INSN
(
insn
);
CLEAR_HARD_REG_SET
(
reg_reloaded_died
);
for
(
j
=
0
;
j
<
reload_n_operands
;
j
++
)
input_reload_insns
[
j
]
=
input_address_reload_insns
[
j
]
=
inpaddr_address_reload_insns
[
j
]
=
output_reload_insns
[
j
]
=
output_address_reload_insns
[
j
]
=
outaddr_address_reload_insns
[
j
]
=
other_output_reload_insns
[
j
]
=
0
;
other_input_address_reload_insns
=
0
;
other_input_reload_insns
=
0
;
operand_reload_insns
=
0
;
other_operand_reload_insns
=
0
;
/* Now output the instructions to copy the data into and out of the
reload registers. Do these in the order that the reloads were reported,
since reloads of base and index registers precede reloads of operands
and the operands may need the base and index registers reloaded. */
for
(
j
=
0
;
j
<
n_reloads
;
j
++
)
{
if
(
rld
[
j
].
reg_rtx
&&
REGNO
(
rld
[
j
].
reg_rtx
)
<
FIRST_PSEUDO_REGISTER
)
new_spill_reg_store
[
REGNO
(
rld
[
j
].
reg_rtx
)]
=
0
;
do_input_reload
(
chain
,
rld
+
j
,
j
);
do_output_reload
(
chain
,
rld
+
j
,
j
);
}
/* Now write all the insns we made for reloads in the order expected by
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment