After the previous patch there are cases where we want to constrain operands to any enabled alternative and cases where we want to also take size/speed preferences into account. The former applies when constraining an existing instruction (which might originally have been in a block with a different size/speed choice) or when making global decisions. The latter applies when evaluating a potential optimisation.
This patch therefore passes the mask of allowable alternatives as a parameter to constrain_operands. Richard 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. Index: gcc/recog.h =================================================================== --- gcc/recog.h 2014-10-17 15:50:02.000000000 +0100 +++ gcc/recog.h 2014-10-17 15:50:02.627695847 +0100 @@ -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 @@ #define this_target_recog (&default_targ 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 (); Index: gcc/recog.c =================================================================== --- gcc/recog.c 2014-10-17 15:50:02.000000000 +0100 +++ gcc/recog.c 2014-10-17 15:50:02.627695847 +0100 @@ -155,8 +155,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; } @@ -360,7 +361,7 @@ insn_invalid_p (rtx_insn *insn, bool in_ { extract_insn (insn); - if (! constrain_operands (1)) + if (! constrain_operands (1, get_preferred_alternatives (insn))) return 1; } @@ -2159,6 +2160,21 @@ get_preferred_alternatives (rtx_insn *in 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, @@ -2199,7 +2215,7 @@ extract_insn_cached (rtx_insn *insn) 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); } @@ -2210,16 +2226,17 @@ extract_constrain_insn_cached (rtx_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; } @@ -2495,7 +2512,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. @@ -2527,7 +2545,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]; @@ -2554,7 +2572,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; @@ -2836,7 +2854,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; } Index: gcc/caller-save.c =================================================================== --- gcc/caller-save.c 2014-10-17 15:50:02.000000000 +0100 +++ gcc/caller-save.c 2014-10-17 15:50:02.611696037 +0100 @@ -138,15 +138,17 @@ reg_save_code (int reg, enum machine_mod 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) Index: gcc/ira.c =================================================================== --- gcc/ira.c 2014-10-17 15:50:02.000000000 +0100 +++ gcc/ira.c 2014-10-17 15:50:02.623695895 +0100 @@ -1760,7 +1760,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); } Index: gcc/postreload-gcse.c =================================================================== --- gcc/postreload-gcse.c 2014-10-17 15:50:02.000000000 +0100 +++ gcc/postreload-gcse.c 2014-10-17 15:50:02.627695847 +0100 @@ -1003,10 +1003,11 @@ eliminate_partially_redundant_load (basi /* 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)) { Index: gcc/ree.c =================================================================== --- gcc/ree.c 2014-10-17 15:50:02.000000000 +0100 +++ gcc/ree.c 2014-10-17 15:50:02.627695847 +0100 @@ -762,7 +762,8 @@ combine_reaching_defs (ext_cand *cand, c 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; @@ -812,7 +813,7 @@ combine_reaching_defs (ext_cand *cand, c 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; } Index: gcc/reload.c =================================================================== --- gcc/reload.c 2014-10-17 15:50:02.000000000 +0100 +++ gcc/reload.c 2014-10-17 15:50:02.627695847 +0100 @@ -913,7 +913,7 @@ can_reload_into (rtx in, int regno, enum 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; Index: gcc/reload1.c =================================================================== --- gcc/reload1.c 2014-10-17 15:50:02.000000000 +0100 +++ gcc/reload1.c 2014-10-17 15:50:02.627695847 +0100 @@ -1257,7 +1257,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"); @@ -4709,7 +4709,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 " @@ -4792,7 +4794,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 @@ -5719,7 +5722,7 @@ gen_reload_chain_without_interm_reg_p (i /* 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); @@ -7389,7 +7392,7 @@ emit_input_reload_insns (struct insn_cha 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 @@ -8576,7 +8579,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; } @@ -9213,7 +9216,7 @@ inc_for_reload (rtx reloadreg, rtx in, r 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 Index: gcc/reorg.c =================================================================== --- gcc/reorg.c 2014-10-17 15:50:02.000000000 +0100 +++ gcc/reorg.c 2014-10-17 15:50:02.627695847 +0100 @@ -2764,7 +2764,8 @@ fill_slots_from_thread (rtx_insn *insn, 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; Index: gcc/config/i386/i386.c =================================================================== --- gcc/config/i386/i386.c 2014-10-17 15:50:02.000000000 +0100 +++ gcc/config/i386/i386.c 2014-10-17 15:50:02.619695944 +0100 @@ -25300,7 +25300,7 @@ ix86_attr_length_address_default (rtx_in 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]; Index: gcc/config/pa/pa.c =================================================================== --- gcc/config/pa/pa.c 2014-10-17 15:50:02.000000000 +0100 +++ gcc/config/pa/pa.c 2014-10-17 15:50:02.623695895 +0100 @@ -9199,8 +9199,10 @@ pa_can_combine_p (rtx_insn *new_rtx, rtx 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) Index: gcc/config/rl78/rl78.c =================================================================== --- gcc/config/rl78/rl78.c 2014-10-17 15:50:02.000000000 +0100 +++ gcc/config/rl78/rl78.c 2014-10-17 15:50:02.623695895 +0100 @@ -2165,7 +2165,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"); @@ -2194,7 +2194,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; Index: gcc/config/sh/sh.md =================================================================== --- gcc/config/sh/sh.md 2014-10-17 15:50:02.000000000 +0100 +++ gcc/config/sh/sh.md 2014-10-17 15:50:02.623695895 +0100 @@ -1567,7 +1567,7 @@ (define_peephole2 (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 @@ -1594,14 +1594,16 @@ (define_peephole2 /* ??? 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: Index: gcc/final.c =================================================================== --- gcc/final.c 2014-10-17 15:50:02.000000000 +0100 +++ gcc/final.c 2014-10-17 15:50:02.623695895 +0100 @@ -2929,7 +2929,7 @@ final_scan_insn (rtx_insn *insn, FILE *f 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