diff options
Diffstat (limited to 'gcc/emit-rtl.c')
-rw-r--r-- | gcc/emit-rtl.c | 300 |
1 files changed, 142 insertions, 158 deletions
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 0d9be17fe94..172a82d3b4b 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -925,7 +925,11 @@ subreg_hard_regno (x, check_mode) abort (); if (check_mode && ! HARD_REGNO_MODE_OK (base_regno, GET_MODE (reg))) abort (); - +#ifdef ENABLE_CHECKING + if (!subreg_offset_representable_p (REGNO (reg), GET_MODE (reg), + SUBREG_BYTE (x), mode)) + abort (); +#endif /* Catch non-congruent offsets too. */ byte_offset = SUBREG_BYTE (x); if ((byte_offset % GET_MODE_SIZE (mode)) != 0) @@ -1800,11 +1804,14 @@ set_mem_attributes_minus_bitpos (ref, t, objectp, bitpos) else if (TREE_CODE (t) == ARRAY_REF) { tree off_tree = size_zero_node; + /* We can't modify t, because we use it at the end of the + function. */ + tree t2 = t; do { - tree index = TREE_OPERAND (t, 1); - tree array = TREE_OPERAND (t, 0); + tree index = TREE_OPERAND (t2, 1); + tree array = TREE_OPERAND (t2, 0); tree domain = TYPE_DOMAIN (TREE_TYPE (array)); tree low_bound = (domain ? TYPE_MIN_VALUE (domain) : 0); tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (array))); @@ -1822,7 +1829,7 @@ set_mem_attributes_minus_bitpos (ref, t, objectp, bitpos) component to one. */ if (! TREE_CONSTANT (index) && contains_placeholder_p (index)) - index = build (WITH_RECORD_EXPR, TREE_TYPE (index), index, t); + index = build (WITH_RECORD_EXPR, TREE_TYPE (index), index, t2); if (! TREE_CONSTANT (unit_size) && contains_placeholder_p (unit_size)) unit_size = build (WITH_RECORD_EXPR, sizetype, @@ -1834,28 +1841,28 @@ set_mem_attributes_minus_bitpos (ref, t, objectp, bitpos) index, unit_size)), off_tree)); - t = TREE_OPERAND (t, 0); + t2 = TREE_OPERAND (t2, 0); } - while (TREE_CODE (t) == ARRAY_REF); + while (TREE_CODE (t2) == ARRAY_REF); - if (DECL_P (t)) + if (DECL_P (t2)) { - expr = t; + expr = t2; offset = NULL; if (host_integerp (off_tree, 1)) { HOST_WIDE_INT ioff = tree_low_cst (off_tree, 1); HOST_WIDE_INT aoff = (ioff & -ioff) * BITS_PER_UNIT; - align = DECL_ALIGN (t); + align = DECL_ALIGN (t2); if (aoff && aoff < align) align = aoff; offset = GEN_INT (ioff); apply_bitpos = bitpos; } } - else if (TREE_CODE (t) == COMPONENT_REF) + else if (TREE_CODE (t2) == COMPONENT_REF) { - expr = component_ref_for_mem_expr (t); + expr = component_ref_for_mem_expr (t2); if (host_integerp (off_tree, 1)) { offset = GEN_INT (tree_low_cst (off_tree, 1)); @@ -1865,10 +1872,10 @@ set_mem_attributes_minus_bitpos (ref, t, objectp, bitpos) the size we got from the type? */ } else if (flag_argument_noalias > 1 - && TREE_CODE (t) == INDIRECT_REF - && TREE_CODE (TREE_OPERAND (t, 0)) == PARM_DECL) + && TREE_CODE (t2) == INDIRECT_REF + && TREE_CODE (TREE_OPERAND (t2, 0)) == PARM_DECL) { - expr = t; + expr = t2; offset = NULL; } } @@ -3203,6 +3210,8 @@ try_split (pat, trial, last) rtx tem; rtx note, seq; int probability; + rtx insn_last, insn; + int njumps = 0; if (any_condjump_p (trial) && (note = find_reg_note (trial, REG_BR_PROB, 0))) @@ -3221,172 +3230,147 @@ try_split (pat, trial, last) after = NEXT_INSN (after); } - if (seq) + if (!seq) + return trial; + + /* Avoid infinite loop if any insn of the result matches + the original pattern. */ + insn_last = seq; + while (1) { - /* Sometimes there will be only one insn in that list, this case will - normally arise only when we want it in turn to be split (SFmode on - the 29k is an example). */ - if (NEXT_INSN (seq) != NULL_RTX) - { - rtx insn_last, insn; - int njumps = 0; + if (INSN_P (insn_last) + && rtx_equal_p (PATTERN (insn_last), pat)) + return trial; + if (!NEXT_INSN (insn_last)) + break; + insn_last = NEXT_INSN (insn_last); + } - /* Avoid infinite loop if any insn of the result matches - the original pattern. */ - insn_last = seq; - while (1) + /* Mark labels. */ + for (insn = insn_last; insn ; insn = PREV_INSN (insn)) + { + if (GET_CODE (insn) == JUMP_INSN) + { + mark_jump_label (PATTERN (insn), insn, 0); + njumps++; + if (probability != -1 + && any_condjump_p (insn) + && !find_reg_note (insn, REG_BR_PROB, 0)) { - if (INSN_P (insn_last) - && rtx_equal_p (PATTERN (insn_last), pat)) - return trial; - if (NEXT_INSN (insn_last) == NULL_RTX) - break; - insn_last = NEXT_INSN (insn_last); + /* We can preserve the REG_BR_PROB notes only if exactly + one jump is created, otherwise the machine description + is responsible for this step using + split_branch_probability variable. */ + if (njumps != 1) + abort (); + REG_NOTES (insn) + = gen_rtx_EXPR_LIST (REG_BR_PROB, + GEN_INT (probability), + REG_NOTES (insn)); } + } + } - /* Mark labels. */ + /* If we are splitting a CALL_INSN, look for the CALL_INSN + in SEQ and copy our CALL_INSN_FUNCTION_USAGE to it. */ + if (GET_CODE (trial) == CALL_INSN) + { + for (insn = insn_last; insn ; insn = PREV_INSN (insn)) + if (GET_CODE (insn) == CALL_INSN) + { + CALL_INSN_FUNCTION_USAGE (insn) + = CALL_INSN_FUNCTION_USAGE (trial); + SIBLING_CALL_P (insn) = SIBLING_CALL_P (trial); + } + } + + /* Copy notes, particularly those related to the CFG. */ + for (note = REG_NOTES (trial); note; note = XEXP (note, 1)) + { + switch (REG_NOTE_KIND (note)) + { + case REG_EH_REGION: insn = insn_last; while (insn != NULL_RTX) { - if (GET_CODE (insn) == JUMP_INSN) - { - mark_jump_label (PATTERN (insn), insn, 0); - njumps++; - if (probability != -1 - && any_condjump_p (insn) - && !find_reg_note (insn, REG_BR_PROB, 0)) - { - /* We can preserve the REG_BR_PROB notes only if exactly - one jump is created, otherwise the machine description - is responsible for this step using - split_branch_probability variable. */ - if (njumps != 1) - abort (); - REG_NOTES (insn) - = gen_rtx_EXPR_LIST (REG_BR_PROB, - GEN_INT (probability), - REG_NOTES (insn)); - } - } - + if (GET_CODE (insn) == CALL_INSN + || (flag_non_call_exceptions + && may_trap_p (PATTERN (insn)))) + REG_NOTES (insn) + = gen_rtx_EXPR_LIST (REG_EH_REGION, + XEXP (note, 0), + REG_NOTES (insn)); insn = PREV_INSN (insn); } + break; - /* If we are splitting a CALL_INSN, look for the CALL_INSN - in SEQ and copy our CALL_INSN_FUNCTION_USAGE to it. */ - if (GET_CODE (trial) == CALL_INSN) - { - insn = insn_last; - while (insn != NULL_RTX) - { - if (GET_CODE (insn) == CALL_INSN) - CALL_INSN_FUNCTION_USAGE (insn) - = CALL_INSN_FUNCTION_USAGE (trial); - - insn = PREV_INSN (insn); - } - } - - /* Copy notes, particularly those related to the CFG. */ - for (note = REG_NOTES (trial); note; note = XEXP (note, 1)) + case REG_NORETURN: + case REG_SETJMP: + case REG_ALWAYS_RETURN: + insn = insn_last; + while (insn != NULL_RTX) { - switch (REG_NOTE_KIND (note)) - { - case REG_EH_REGION: - insn = insn_last; - while (insn != NULL_RTX) - { - if (GET_CODE (insn) == CALL_INSN - || (flag_non_call_exceptions - && may_trap_p (PATTERN (insn)))) - REG_NOTES (insn) - = gen_rtx_EXPR_LIST (REG_EH_REGION, - XEXP (note, 0), - REG_NOTES (insn)); - insn = PREV_INSN (insn); - } - break; - - case REG_NORETURN: - case REG_SETJMP: - case REG_ALWAYS_RETURN: - insn = insn_last; - while (insn != NULL_RTX) - { - if (GET_CODE (insn) == CALL_INSN) - REG_NOTES (insn) - = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note), - XEXP (note, 0), - REG_NOTES (insn)); - insn = PREV_INSN (insn); - } - break; - - case REG_NON_LOCAL_GOTO: - insn = insn_last; - while (insn != NULL_RTX) - { - if (GET_CODE (insn) == JUMP_INSN) - REG_NOTES (insn) - = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note), - XEXP (note, 0), - REG_NOTES (insn)); - insn = PREV_INSN (insn); - } - break; - - default: - break; - } + if (GET_CODE (insn) == CALL_INSN) + REG_NOTES (insn) + = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note), + XEXP (note, 0), + REG_NOTES (insn)); + insn = PREV_INSN (insn); } + break; - /* If there are LABELS inside the split insns increment the - usage count so we don't delete the label. */ - if (GET_CODE (trial) == INSN) + case REG_NON_LOCAL_GOTO: + insn = insn_last; + while (insn != NULL_RTX) { - insn = insn_last; - while (insn != NULL_RTX) - { - if (GET_CODE (insn) == INSN) - mark_label_nuses (PATTERN (insn)); - - insn = PREV_INSN (insn); - } + if (GET_CODE (insn) == JUMP_INSN) + REG_NOTES (insn) + = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note), + XEXP (note, 0), + REG_NOTES (insn)); + insn = PREV_INSN (insn); } + break; - tem = emit_insn_after_scope (seq, trial, INSN_SCOPE (trial)); - - delete_insn (trial); - if (has_barrier) - emit_barrier_after (tem); - - /* Recursively call try_split for each new insn created; by the - time control returns here that insn will be fully split, so - set LAST and continue from the insn after the one returned. - We can't use next_active_insn here since AFTER may be a note. - Ignore deleted insns, which can be occur if not optimizing. */ - for (tem = NEXT_INSN (before); tem != after; tem = NEXT_INSN (tem)) - if (! INSN_DELETED_P (tem) && INSN_P (tem)) - tem = try_split (PATTERN (tem), tem, 1); + default: + break; } - /* Avoid infinite loop if the result matches the original pattern. */ - else if (rtx_equal_p (PATTERN (seq), pat)) - return trial; - else + } + + /* If there are LABELS inside the split insns increment the + usage count so we don't delete the label. */ + if (GET_CODE (trial) == INSN) + { + insn = insn_last; + while (insn != NULL_RTX) { - PATTERN (trial) = PATTERN (seq); - INSN_CODE (trial) = -1; - try_split (PATTERN (trial), trial, last); - } + if (GET_CODE (insn) == INSN) + mark_label_nuses (PATTERN (insn)); - /* Return either the first or the last insn, depending on which was - requested. */ - return last - ? (after ? PREV_INSN (after) : last_insn) - : NEXT_INSN (before); + insn = PREV_INSN (insn); + } } - return trial; + tem = emit_insn_after_scope (seq, trial, INSN_SCOPE (trial)); + + delete_insn (trial); + if (has_barrier) + emit_barrier_after (tem); + + /* Recursively call try_split for each new insn created; by the + time control returns here that insn will be fully split, so + set LAST and continue from the insn after the one returned. + We can't use next_active_insn here since AFTER may be a note. + Ignore deleted insns, which can be occur if not optimizing. */ + for (tem = NEXT_INSN (before); tem != after; tem = NEXT_INSN (tem)) + if (! INSN_DELETED_P (tem) && INSN_P (tem)) + tem = try_split (PATTERN (tem), tem, 1); + + /* Return either the first or the last insn, depending on which was + requested. */ + return last + ? (after ? PREV_INSN (after) : last_insn) + : NEXT_INSN (before); } /* Make and return an INSN rtx, initializing all its slots. |