recog.h (constrain_operands): Add an alternative_mask parameter.
gcc/ * recog.h (constrain_operands): Add an alternative_mask parameter. (constrain_operands_cached): Likewise. (get_preferred_alternatives): Declare new form. * recog.c (get_preferred_alternatives): New bb-taking instance. (constrain_operands): Take the set of available alternatives as a parameter. (check_asm_operands, insn_invalid_p, extract_constrain_insn) (extract_constrain_insn_cached): Update calls to constrain_operands. * caller-save.c (reg_save_code): Likewise. * ira.c (setup_prohibited_mode_move_regs): Likewise. * postreload-gcse.c (eliminate_partially_redundant_load): Likewise. * ree.c (combine_reaching_defs): Likewise. * reload.c (can_reload_into): Likewise. * reload1.c (reload, reload_as_needed, inc_for_reload): Likewise. (gen_reload_chain_without_interm_reg_p, emit_input_reload_insns) (emit_insn_if_valid_for_reload): Likewise. * reorg.c (fill_slots_from_thread): Likewise. * config/i386/i386.c (ix86_attr_length_address_default): Likewise. * config/pa/pa.c (pa_can_combine_p): Likewise. * config/rl78/rl78.c (insn_ok_now): Likewise. * config/sh/sh.md (define_peephole2): Likewise. * final.c (final_scan_insn): Update call to constrain_operands_cached. From-SVN: r216555
This commit is contained in:
parent
9840b2fa87
commit
daca1a96af
@ -1,3 +1,28 @@
|
||||
2014-10-22 Richard Sandiford <richard.sandiford@arm.com>
|
||||
|
||||
* recog.h (constrain_operands): Add an alternative_mask parameter.
|
||||
(constrain_operands_cached): Likewise.
|
||||
(get_preferred_alternatives): Declare new form.
|
||||
* recog.c (get_preferred_alternatives): New bb-taking instance.
|
||||
(constrain_operands): Take the set of available alternatives as
|
||||
a parameter.
|
||||
(check_asm_operands, insn_invalid_p, extract_constrain_insn)
|
||||
(extract_constrain_insn_cached): Update calls to constrain_operands.
|
||||
* caller-save.c (reg_save_code): Likewise.
|
||||
* ira.c (setup_prohibited_mode_move_regs): Likewise.
|
||||
* postreload-gcse.c (eliminate_partially_redundant_load): Likewise.
|
||||
* ree.c (combine_reaching_defs): Likewise.
|
||||
* reload.c (can_reload_into): Likewise.
|
||||
* reload1.c (reload, reload_as_needed, inc_for_reload): Likewise.
|
||||
(gen_reload_chain_without_interm_reg_p, emit_input_reload_insns)
|
||||
(emit_insn_if_valid_for_reload): Likewise.
|
||||
* reorg.c (fill_slots_from_thread): Likewise.
|
||||
* config/i386/i386.c (ix86_attr_length_address_default): Likewise.
|
||||
* config/pa/pa.c (pa_can_combine_p): Likewise.
|
||||
* config/rl78/rl78.c (insn_ok_now): Likewise.
|
||||
* config/sh/sh.md (define_peephole2): Likewise.
|
||||
* final.c (final_scan_insn): Update call to constrain_operands_cached.
|
||||
|
||||
2014-10-22 Richard Sandiford <richard.sandiford@arm.com>
|
||||
|
||||
* doc/md.texi: Document "preferred_for_size" and "preferred_for_speed"
|
||||
|
@ -143,15 +143,17 @@ reg_save_code (int reg, enum machine_mode mode)
|
||||
cached_reg_restore_code[reg][mode] = recog_memoized (restinsn);
|
||||
|
||||
/* Now extract both insns and see if we can meet their
|
||||
constraints. */
|
||||
constraints. We don't know here whether the save and restore will
|
||||
be in size- or speed-tuned code, so just use the set of enabled
|
||||
alternatives. */
|
||||
ok = (cached_reg_save_code[reg][mode] != -1
|
||||
&& cached_reg_restore_code[reg][mode] != -1);
|
||||
if (ok)
|
||||
{
|
||||
extract_insn (saveinsn);
|
||||
ok = constrain_operands (1);
|
||||
ok = constrain_operands (1, get_enabled_alternatives (saveinsn));
|
||||
extract_insn (restinsn);
|
||||
ok &= constrain_operands (1);
|
||||
ok &= constrain_operands (1, get_enabled_alternatives (restinsn));
|
||||
}
|
||||
|
||||
if (! ok)
|
||||
|
@ -25467,7 +25467,7 @@ ix86_attr_length_address_default (rtx_insn *insn)
|
||||
for (i = recog_data.n_operands - 1; i >= 0; --i)
|
||||
if (MEM_P (recog_data.operand[i]))
|
||||
{
|
||||
constrain_operands_cached (reload_completed);
|
||||
constrain_operands_cached (insn, reload_completed);
|
||||
if (which_alternative != -1)
|
||||
{
|
||||
const char *constraints = recog_data.constraints[i];
|
||||
|
@ -9064,8 +9064,10 @@ pa_can_combine_p (rtx_insn *new_rtx, rtx_insn *anchor, rtx_insn *floater,
|
||||
XVECEXP (PATTERN (new_rtx), 0, 1) = PATTERN (floater);
|
||||
INSN_CODE (new_rtx) = -1;
|
||||
insn_code_number = recog_memoized (new_rtx);
|
||||
basic_block bb = BLOCK_FOR_INSN (anchor);
|
||||
if (insn_code_number < 0
|
||||
|| (extract_insn (new_rtx), ! constrain_operands (1)))
|
||||
|| (extract_insn (new_rtx),
|
||||
!constrain_operands (1, get_preferred_alternatives (new_rtx, bb)))
|
||||
return 0;
|
||||
|
||||
if (reversed)
|
||||
|
@ -2170,7 +2170,7 @@ insn_ok_now (rtx_insn *insn)
|
||||
if (recog (pattern, insn, 0) > -1)
|
||||
{
|
||||
extract_insn (insn);
|
||||
if (constrain_operands (1))
|
||||
if (constrain_operands (1, get_preferred_alternatives (insn)))
|
||||
{
|
||||
#if DEBUG_ALLOC
|
||||
fprintf (stderr, "\033[32m");
|
||||
@ -2199,7 +2199,7 @@ insn_ok_now (rtx_insn *insn)
|
||||
if (recog (pattern, insn, 0) > -1)
|
||||
{
|
||||
extract_insn (insn);
|
||||
if (constrain_operands (0))
|
||||
if (constrain_operands (0, get_preferred_alternatives (insn)))
|
||||
{
|
||||
cfun->machine->virt_insns_ok = 0;
|
||||
return false;
|
||||
|
@ -1580,7 +1580,7 @@
|
||||
(set (match_dup 4) (match_dup 5))]
|
||||
{
|
||||
rtx set1, set2;
|
||||
rtx_insn *insn2;
|
||||
rtx_insn *insn1, *insn2;
|
||||
rtx replacements[4];
|
||||
|
||||
/* We want to replace occurrences of operands[0] with operands[1] and
|
||||
@ -1607,14 +1607,16 @@
|
||||
/* ??? The last insn might be a jump insn, but the generic peephole2 code
|
||||
always uses emit_insn. */
|
||||
/* Check that we don't violate matching constraints or earlyclobbers. */
|
||||
extract_insn (emit_insn (set1));
|
||||
if (! constrain_operands (1))
|
||||
basic_block bb = BLOCK_FOR_INSN (peep2_next_insn (2));
|
||||
insn1 = emit_insn (set1);
|
||||
extract_insn (insn1);
|
||||
if (! constrain_operands (1, get_preferred_alternatives (insn1, bb)))
|
||||
goto failure;
|
||||
insn2 = emit (set2);
|
||||
if (GET_CODE (insn2) == BARRIER)
|
||||
goto failure;
|
||||
extract_insn (insn2);
|
||||
if (! constrain_operands (1))
|
||||
if (! constrain_operands (1, get_preferred_alternatives (insn2, bb)))
|
||||
{
|
||||
rtx tmp;
|
||||
failure:
|
||||
|
@ -2934,7 +2934,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
|
||||
print_rtx_head = "";
|
||||
}
|
||||
|
||||
if (! constrain_operands_cached (1))
|
||||
if (! constrain_operands_cached (insn, 1))
|
||||
fatal_insn_not_found (insn);
|
||||
|
||||
/* Some target machines need to prescan each insn before
|
||||
|
@ -1765,7 +1765,9 @@ setup_prohibited_mode_move_regs (void)
|
||||
if (INSN_CODE (move_insn) < 0)
|
||||
continue;
|
||||
extract_insn (move_insn);
|
||||
if (! constrain_operands (1))
|
||||
/* We don't know whether the move will be in code that is optimized
|
||||
for size or speed, so consider all enabled alternatives. */
|
||||
if (! constrain_operands (1, get_enabled_alternatives (move_insn)))
|
||||
continue;
|
||||
CLEAR_HARD_REG_BIT (ira_prohibited_mode_move_regs[i], j);
|
||||
}
|
||||
|
@ -1008,10 +1008,11 @@ eliminate_partially_redundant_load (basic_block bb, rtx_insn *insn,
|
||||
|
||||
/* Make sure we can generate a move from register avail_reg to
|
||||
dest. */
|
||||
extract_insn (as_a <rtx_insn *> (
|
||||
gen_move_insn (copy_rtx (dest),
|
||||
copy_rtx (avail_reg))));
|
||||
if (! constrain_operands (1)
|
||||
rtx_insn *move = as_a <rtx_insn *>
|
||||
(gen_move_insn (copy_rtx (dest), copy_rtx (avail_reg)));
|
||||
extract_insn (move);
|
||||
if (! constrain_operands (1, get_preferred_alternatives (insn,
|
||||
pred_bb))
|
||||
|| reg_killed_on_edge (avail_reg, pred)
|
||||
|| reg_used_on_edge (dest, pred))
|
||||
{
|
||||
|
42
gcc/recog.c
42
gcc/recog.c
@ -160,8 +160,9 @@ check_asm_operands (rtx x)
|
||||
if (reload_completed)
|
||||
{
|
||||
/* ??? Doh! We've not got the wrapping insn. Cook one up. */
|
||||
extract_insn (make_insn_raw (x));
|
||||
constrain_operands (1);
|
||||
rtx_insn *insn = make_insn_raw (x);
|
||||
extract_insn (insn);
|
||||
constrain_operands (1, get_enabled_alternatives (insn));
|
||||
return which_alternative >= 0;
|
||||
}
|
||||
|
||||
@ -365,7 +366,7 @@ insn_invalid_p (rtx_insn *insn, bool in_group)
|
||||
{
|
||||
extract_insn (insn);
|
||||
|
||||
if (! constrain_operands (1))
|
||||
if (! constrain_operands (1, get_preferred_alternatives (insn)))
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -2164,6 +2165,21 @@ get_preferred_alternatives (rtx_insn *insn)
|
||||
return get_bool_attr_mask (insn, BA_PREFERRED_FOR_SIZE);
|
||||
}
|
||||
|
||||
/* Return the set of alternatives of INSN that are allowed by the current
|
||||
target and are preferred for the size/speed optimization choice
|
||||
associated with BB. Passing a separate BB is useful if INSN has not
|
||||
been emitted yet or if we are considering moving it to a different
|
||||
block. */
|
||||
|
||||
alternative_mask
|
||||
get_preferred_alternatives (rtx_insn *insn, basic_block bb)
|
||||
{
|
||||
if (optimize_bb_for_speed_p (bb))
|
||||
return get_bool_attr_mask (insn, BA_PREFERRED_FOR_SPEED);
|
||||
else
|
||||
return get_bool_attr_mask (insn, BA_PREFERRED_FOR_SIZE);
|
||||
}
|
||||
|
||||
/* Assert that the cached boolean attributes for INSN are still accurate.
|
||||
The backend is required to define these attributes in a way that only
|
||||
depends on the current target (rather than operands, compiler phase,
|
||||
@ -2204,7 +2220,7 @@ void
|
||||
extract_constrain_insn (rtx_insn *insn)
|
||||
{
|
||||
extract_insn (insn);
|
||||
if (!constrain_operands (reload_completed))
|
||||
if (!constrain_operands (reload_completed, get_enabled_alternatives (insn)))
|
||||
fatal_insn_not_found (insn);
|
||||
}
|
||||
|
||||
@ -2215,16 +2231,17 @@ extract_constrain_insn_cached (rtx_insn *insn)
|
||||
{
|
||||
extract_insn_cached (insn);
|
||||
if (which_alternative == -1
|
||||
&& !constrain_operands (reload_completed))
|
||||
&& !constrain_operands (reload_completed,
|
||||
get_enabled_alternatives (insn)))
|
||||
fatal_insn_not_found (insn);
|
||||
}
|
||||
|
||||
/* Do cached constrain_operands and complain about failures. */
|
||||
/* Do cached constrain_operands on INSN and complain about failures. */
|
||||
int
|
||||
constrain_operands_cached (int strict)
|
||||
constrain_operands_cached (rtx_insn *insn, int strict)
|
||||
{
|
||||
if (which_alternative == -1)
|
||||
return constrain_operands (strict);
|
||||
return constrain_operands (strict, get_enabled_alternatives (insn));
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
@ -2500,7 +2517,8 @@ preprocess_constraints (rtx insn)
|
||||
}
|
||||
|
||||
/* Check the operands of an insn against the insn's operand constraints
|
||||
and return 1 if they are valid.
|
||||
and return 1 if they match any of the alternatives in ALTERNATIVES.
|
||||
|
||||
The information about the insn's operands, constraints, operand modes
|
||||
etc. is obtained from the global variables set up by extract_insn.
|
||||
|
||||
@ -2532,7 +2550,7 @@ struct funny_match
|
||||
};
|
||||
|
||||
int
|
||||
constrain_operands (int strict)
|
||||
constrain_operands (int strict, alternative_mask alternatives)
|
||||
{
|
||||
const char *constraints[MAX_RECOG_OPERANDS];
|
||||
int matching_operands[MAX_RECOG_OPERANDS];
|
||||
@ -2559,7 +2577,7 @@ constrain_operands (int strict)
|
||||
int lose = 0;
|
||||
funny_match_index = 0;
|
||||
|
||||
if (!TEST_BIT (recog_data.enabled_alternatives, which_alternative))
|
||||
if (!TEST_BIT (alternatives, which_alternative))
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -2841,7 +2859,7 @@ constrain_operands (int strict)
|
||||
/* If we are about to reject this, but we are not to test strictly,
|
||||
try a very loose test. Only return failure if it fails also. */
|
||||
if (strict == 0)
|
||||
return constrain_operands (-1);
|
||||
return constrain_operands (-1, alternatives);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
@ -95,8 +95,8 @@ extern void confirm_change_group (void);
|
||||
extern int apply_change_group (void);
|
||||
extern int num_validated_changes (void);
|
||||
extern void cancel_changes (int);
|
||||
extern int constrain_operands (int);
|
||||
extern int constrain_operands_cached (int);
|
||||
extern int constrain_operands (int, alternative_mask);
|
||||
extern int constrain_operands_cached (rtx_insn *, int);
|
||||
extern int memory_address_addr_space_p (enum machine_mode, rtx, addr_space_t);
|
||||
#define memory_address_p(mode,addr) \
|
||||
memory_address_addr_space_p ((mode), (addr), ADDR_SPACE_GENERIC)
|
||||
@ -414,6 +414,7 @@ extern struct target_recog *this_target_recog;
|
||||
|
||||
alternative_mask get_enabled_alternatives (rtx_insn *);
|
||||
alternative_mask get_preferred_alternatives (rtx_insn *);
|
||||
alternative_mask get_preferred_alternatives (rtx_insn *, basic_block);
|
||||
bool check_bool_attrs (rtx_insn *);
|
||||
|
||||
void recog_init ();
|
||||
|
@ -767,7 +767,8 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
|
||||
This is merely to keep the test for safety and updating the insn
|
||||
stream simple. Also ensure that within the block the candidate
|
||||
follows the defining insn. */
|
||||
if (BLOCK_FOR_INSN (cand->insn) != BLOCK_FOR_INSN (def_insn)
|
||||
basic_block bb = BLOCK_FOR_INSN (cand->insn);
|
||||
if (bb != BLOCK_FOR_INSN (def_insn)
|
||||
|| DF_INSN_LUID (def_insn) > DF_INSN_LUID (cand->insn))
|
||||
return false;
|
||||
|
||||
@ -817,7 +818,7 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
|
||||
if (recog_memoized (insn) == -1)
|
||||
return false;
|
||||
extract_insn (insn);
|
||||
if (!constrain_operands (1))
|
||||
if (!constrain_operands (1, get_preferred_alternatives (insn, bb)))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -918,7 +918,7 @@ can_reload_into (rtx in, int regno, enum machine_mode mode)
|
||||
if (recog_memoized (test_insn) >= 0)
|
||||
{
|
||||
extract_insn (test_insn);
|
||||
r = constrain_operands (1);
|
||||
r = constrain_operands (1, get_enabled_alternatives (test_insn));
|
||||
}
|
||||
recog_data = save_recog_data;
|
||||
return r;
|
||||
|
@ -1261,7 +1261,7 @@ reload (rtx_insn *first, int global)
|
||||
if (asm_noperands (PATTERN (insn)) >= 0)
|
||||
{
|
||||
extract_insn (insn);
|
||||
if (!constrain_operands (1))
|
||||
if (!constrain_operands (1, get_enabled_alternatives (insn)))
|
||||
{
|
||||
error_for_asm (insn,
|
||||
"%<asm%> operand has impossible constraints");
|
||||
@ -4713,7 +4713,9 @@ reload_as_needed (int live_known)
|
||||
if (p != insn && INSN_P (p)
|
||||
&& GET_CODE (PATTERN (p)) != USE
|
||||
&& (recog_memoized (p) < 0
|
||||
|| (extract_insn (p), ! constrain_operands (1))))
|
||||
|| (extract_insn (p),
|
||||
!(constrain_operands (1,
|
||||
get_enabled_alternatives (p))))))
|
||||
{
|
||||
error_for_asm (insn,
|
||||
"%<asm%> operand requires "
|
||||
@ -4796,7 +4798,8 @@ reload_as_needed (int live_known)
|
||||
if (n)
|
||||
{
|
||||
extract_insn (p);
|
||||
n = constrain_operands (1);
|
||||
n = constrain_operands (1,
|
||||
get_enabled_alternatives (p));
|
||||
}
|
||||
|
||||
/* If the constraints were not met, then
|
||||
@ -5723,7 +5726,7 @@ gen_reload_chain_without_interm_reg_p (int r1, int r2)
|
||||
/* We want constrain operands to treat this insn strictly in
|
||||
its validity determination, i.e., the way it would after
|
||||
reload has completed. */
|
||||
result = constrain_operands (1);
|
||||
result = constrain_operands (1, get_enabled_alternatives (insn));
|
||||
}
|
||||
|
||||
delete_insns_since (last);
|
||||
@ -7393,7 +7396,7 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
|
||||
autoincrement addressing mode, then the resulting insn
|
||||
is ill-formed and we must reject this optimization. */
|
||||
extract_insn (temp);
|
||||
if (constrain_operands (1)
|
||||
if (constrain_operands (1, get_enabled_alternatives (temp))
|
||||
#ifdef AUTO_INC_DEC
|
||||
&& ! find_reg_note (temp, REG_INC, reloadreg)
|
||||
#endif
|
||||
@ -8580,7 +8583,7 @@ emit_insn_if_valid_for_reload (rtx pat)
|
||||
/* We want constrain operands to treat this insn strictly in its
|
||||
validity determination, i.e., the way it would after reload has
|
||||
completed. */
|
||||
if (constrain_operands (1))
|
||||
if (constrain_operands (1, get_enabled_alternatives (insn)))
|
||||
return insn;
|
||||
}
|
||||
|
||||
@ -9217,7 +9220,7 @@ inc_for_reload (rtx reloadreg, rtx in, rtx value, int inc_amount)
|
||||
if (code >= 0)
|
||||
{
|
||||
extract_insn (add_insn);
|
||||
if (constrain_operands (1))
|
||||
if (constrain_operands (1, get_enabled_alternatives (add_insn)))
|
||||
{
|
||||
/* If this is a pre-increment and we have incremented the value
|
||||
where it lives, copy the incremented value to RELOADREG to
|
||||
|
@ -2769,7 +2769,8 @@ fill_slots_from_thread (rtx_insn *insn, rtx condition, rtx thread_or_return,
|
||||
insn);
|
||||
|
||||
if (recog_memoized (ninsn) < 0
|
||||
|| (extract_insn (ninsn), ! constrain_operands (1)))
|
||||
|| (extract_insn (ninsn),
|
||||
!constrain_operands (1, get_preferred_alternatives (ninsn))))
|
||||
{
|
||||
delete_related_insns (ninsn);
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user