X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fexpr.c;h=e4bb633d717edb4dd014205866f58e1671da9c4d;hb=43c5cb7038177164b1675b51a587cb9c72b369d4;hp=7e611bd06464ff38a41a10581e2cf0da66ab0f51;hpb=5a574e8bc02ccbac0d8fb40b989a8a17af6917bc;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/expr.c b/gcc/expr.c index 7e611bd0646..e4bb633d717 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -2184,13 +2184,12 @@ copy_blkmode_from_reg (rtx tgtblk, rtx srcreg, tree type) to by CALL_FUSAGE. REG must denote a hard register. */ void -use_reg (rtx *call_fusage, rtx reg) +use_reg_mode (rtx *call_fusage, rtx reg, enum machine_mode mode) { gcc_assert (REG_P (reg) && REGNO (reg) < FIRST_PSEUDO_REGISTER); *call_fusage - = gen_rtx_EXPR_LIST (VOIDmode, - gen_rtx_USE (VOIDmode, reg), *call_fusage); + = gen_rtx_EXPR_LIST (mode, gen_rtx_USE (VOIDmode, reg), *call_fusage); } /* Add USE expressions to *CALL_FUSAGE for each of NREGS consecutive regs, @@ -3548,131 +3547,151 @@ mem_autoinc_base (rtx mem) verified, via immediate operand or auto-inc. If the adjustment cannot be trivially extracted, the return value is INT_MIN. */ -int -fixup_args_size_notes (rtx prev, rtx last, int end_args_size) +HOST_WIDE_INT +find_args_size_adjust (rtx insn) { - int args_size = end_args_size; - bool saw_unknown = false; - rtx insn; + rtx dest, set, pat; + int i; - for (insn = last; insn != prev; insn = PREV_INSN (insn)) - { - rtx dest, set, pat; - HOST_WIDE_INT this_delta = 0; - int i; + pat = PATTERN (insn); + set = NULL; - if (!NONDEBUG_INSN_P (insn)) - continue; - pat = PATTERN (insn); - set = NULL; + /* Look for a call_pop pattern. */ + if (CALL_P (insn)) + { + /* We have to allow non-call_pop patterns for the case + of emit_single_push_insn of a TLS address. */ + if (GET_CODE (pat) != PARALLEL) + return 0; - /* Look for a call_pop pattern. */ - if (CALL_P (insn)) + /* All call_pop have a stack pointer adjust in the parallel. + The call itself is always first, and the stack adjust is + usually last, so search from the end. */ + for (i = XVECLEN (pat, 0) - 1; i > 0; --i) { - /* We have to allow non-call_pop patterns for the case - of emit_single_push_insn of a TLS address. */ - if (GET_CODE (pat) != PARALLEL) + set = XVECEXP (pat, 0, i); + if (GET_CODE (set) != SET) continue; - - /* All call_pop have a stack pointer adjust in the parallel. - The call itself is always first, and the stack adjust is - usually last, so search from the end. */ - for (i = XVECLEN (pat, 0) - 1; i > 0; --i) - { - set = XVECEXP (pat, 0, i); - if (GET_CODE (set) != SET) - continue; - dest = SET_DEST (set); - if (dest == stack_pointer_rtx) - break; - } - /* We'd better have found the stack pointer adjust. */ - if (i == 0) - continue; - /* Fall through to process the extracted SET and DEST - as if it was a standalone insn. */ + dest = SET_DEST (set); + if (dest == stack_pointer_rtx) + break; } - else if (GET_CODE (pat) == SET) - set = pat; - else if ((set = single_set (insn)) != NULL) - ; - else if (GET_CODE (pat) == PARALLEL) + /* We'd better have found the stack pointer adjust. */ + if (i == 0) + return 0; + /* Fall through to process the extracted SET and DEST + as if it was a standalone insn. */ + } + else if (GET_CODE (pat) == SET) + set = pat; + else if ((set = single_set (insn)) != NULL) + ; + else if (GET_CODE (pat) == PARALLEL) + { + /* ??? Some older ports use a parallel with a stack adjust + and a store for a PUSH_ROUNDING pattern, rather than a + PRE/POST_MODIFY rtx. Don't force them to update yet... */ + /* ??? See h8300 and m68k, pushqi1. */ + for (i = XVECLEN (pat, 0) - 1; i >= 0; --i) { - /* ??? Some older ports use a parallel with a stack adjust - and a store for a PUSH_ROUNDING pattern, rather than a - PRE/POST_MODIFY rtx. Don't force them to update yet... */ - /* ??? See h8300 and m68k, pushqi1. */ - for (i = XVECLEN (pat, 0) - 1; i >= 0; --i) - { - set = XVECEXP (pat, 0, i); - if (GET_CODE (set) != SET) - continue; - dest = SET_DEST (set); - if (dest == stack_pointer_rtx) - break; - - /* We do not expect an auto-inc of the sp in the parallel. */ - gcc_checking_assert (mem_autoinc_base (dest) - != stack_pointer_rtx); - gcc_checking_assert (mem_autoinc_base (SET_SRC (set)) - != stack_pointer_rtx); - } - if (i < 0) + set = XVECEXP (pat, 0, i); + if (GET_CODE (set) != SET) continue; + dest = SET_DEST (set); + if (dest == stack_pointer_rtx) + break; + + /* We do not expect an auto-inc of the sp in the parallel. */ + gcc_checking_assert (mem_autoinc_base (dest) != stack_pointer_rtx); + gcc_checking_assert (mem_autoinc_base (SET_SRC (set)) + != stack_pointer_rtx); } + if (i < 0) + return 0; + } + else + return 0; + + dest = SET_DEST (set); + + /* Look for direct modifications of the stack pointer. */ + if (REG_P (dest) && REGNO (dest) == STACK_POINTER_REGNUM) + { + /* Look for a trivial adjustment, otherwise assume nothing. */ + /* Note that the SPU restore_stack_block pattern refers to + the stack pointer in V4SImode. Consider that non-trivial. */ + if (SCALAR_INT_MODE_P (GET_MODE (dest)) + && GET_CODE (SET_SRC (set)) == PLUS + && XEXP (SET_SRC (set), 0) == stack_pointer_rtx + && CONST_INT_P (XEXP (SET_SRC (set), 1))) + return INTVAL (XEXP (SET_SRC (set), 1)); + /* ??? Reload can generate no-op moves, which will be cleaned + up later. Recognize it and continue searching. */ + else if (rtx_equal_p (dest, SET_SRC (set))) + return 0; else - continue; - dest = SET_DEST (set); - - /* Look for direct modifications of the stack pointer. */ - if (REG_P (dest) && REGNO (dest) == STACK_POINTER_REGNUM) - { - gcc_assert (!saw_unknown); - /* Look for a trivial adjustment, otherwise assume nothing. */ - /* Note that the SPU restore_stack_block pattern refers to - the stack pointer in V4SImode. Consider that non-trivial. */ - if (SCALAR_INT_MODE_P (GET_MODE (dest)) - && GET_CODE (SET_SRC (set)) == PLUS - && XEXP (SET_SRC (set), 0) == stack_pointer_rtx - && CONST_INT_P (XEXP (SET_SRC (set), 1))) - this_delta = INTVAL (XEXP (SET_SRC (set), 1)); - /* ??? Reload can generate no-op moves, which will be cleaned - up later. Recognize it and continue searching. */ - else if (rtx_equal_p (dest, SET_SRC (set))) - this_delta = 0; - else - saw_unknown = true; - } + return HOST_WIDE_INT_MIN; + } + else + { + rtx mem, addr; + /* Otherwise only think about autoinc patterns. */ - else if (mem_autoinc_base (dest) == stack_pointer_rtx) + if (mem_autoinc_base (dest) == stack_pointer_rtx) { - rtx addr = XEXP (dest, 0); - gcc_assert (!saw_unknown); - switch (GET_CODE (addr)) - { - case PRE_INC: - case POST_INC: - this_delta = GET_MODE_SIZE (GET_MODE (dest)); - break; - case PRE_DEC: - case POST_DEC: - this_delta = -GET_MODE_SIZE (GET_MODE (dest)); - break; - case PRE_MODIFY: - case POST_MODIFY: - addr = XEXP (addr, 1); - gcc_assert (GET_CODE (addr) == PLUS); - gcc_assert (XEXP (addr, 0) == stack_pointer_rtx); - gcc_assert (CONST_INT_P (XEXP (addr, 1))); - this_delta = INTVAL (XEXP (addr, 1)); - break; - default: - gcc_unreachable (); - } + mem = dest; + gcc_checking_assert (mem_autoinc_base (SET_SRC (set)) + != stack_pointer_rtx); } + else if (mem_autoinc_base (SET_SRC (set)) == stack_pointer_rtx) + mem = SET_SRC (set); else + return 0; + + addr = XEXP (mem, 0); + switch (GET_CODE (addr)) + { + case PRE_INC: + case POST_INC: + return GET_MODE_SIZE (GET_MODE (mem)); + case PRE_DEC: + case POST_DEC: + return -GET_MODE_SIZE (GET_MODE (mem)); + case PRE_MODIFY: + case POST_MODIFY: + addr = XEXP (addr, 1); + gcc_assert (GET_CODE (addr) == PLUS); + gcc_assert (XEXP (addr, 0) == stack_pointer_rtx); + gcc_assert (CONST_INT_P (XEXP (addr, 1))); + return INTVAL (XEXP (addr, 1)); + default: + gcc_unreachable (); + } + } +} + +int +fixup_args_size_notes (rtx prev, rtx last, int end_args_size) +{ + int args_size = end_args_size; + bool saw_unknown = false; + rtx insn; + + for (insn = last; insn != prev; insn = PREV_INSN (insn)) + { + HOST_WIDE_INT this_delta; + + if (!NONDEBUG_INSN_P (insn)) + continue; + + this_delta = find_args_size_adjust (insn); + if (this_delta == 0) continue; + gcc_assert (!saw_unknown); + if (this_delta == HOST_WIDE_INT_MIN) + saw_unknown = true; + add_reg_note (insn, REG_ARGS_SIZE, GEN_INT (args_size)); #ifdef STACK_GROWS_DOWNWARD this_delta = -this_delta; @@ -4354,7 +4373,8 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart, || TREE_CODE (innerdecl) == TARGET_MEM_REF) && !ptr_deref_may_alias_global_p (TREE_OPERAND (innerdecl, 0))) || (DECL_P (innerdecl) - && (DECL_THREAD_LOCAL_P (innerdecl) + && ((TREE_CODE (innerdecl) == VAR_DECL + && DECL_THREAD_LOCAL_P (innerdecl)) || !TREE_STATIC (innerdecl)))) { *bitstart = *bitend = 0; @@ -8003,19 +8023,16 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode, { enum machine_mode innermode = TYPE_MODE (TREE_TYPE (treeop0)); this_optab = usmul_widen_optab; - if (mode == GET_MODE_2XWIDER_MODE (innermode)) + if (find_widening_optab_handler (this_optab, mode, innermode, 0) + != CODE_FOR_nothing) { - if (widening_optab_handler (this_optab, mode, innermode) - != CODE_FOR_nothing) - { - if (TYPE_UNSIGNED (TREE_TYPE (treeop0))) - expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, - EXPAND_NORMAL); - else - expand_operands (treeop0, treeop1, NULL_RTX, &op1, &op0, - EXPAND_NORMAL); - goto binop3; - } + if (TYPE_UNSIGNED (TREE_TYPE (treeop0))) + expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, + EXPAND_NORMAL); + else + expand_operands (treeop0, treeop1, NULL_RTX, &op1, &op0, + EXPAND_NORMAL); + goto binop3; } } /* Check for a multiplication with matching signedness. */ @@ -8030,10 +8047,9 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode, optab other_optab = zextend_p ? smul_widen_optab : umul_widen_optab; this_optab = zextend_p ? umul_widen_optab : smul_widen_optab; - if (mode == GET_MODE_2XWIDER_MODE (innermode) - && TREE_CODE (treeop0) != INTEGER_CST) + if (TREE_CODE (treeop0) != INTEGER_CST) { - if (widening_optab_handler (this_optab, mode, innermode) + if (find_widening_optab_handler (this_optab, mode, innermode, 0) != CODE_FOR_nothing) { expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, @@ -8042,7 +8058,7 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode, unsignedp, this_optab); return REDUCE_BIT_FIELD (temp); } - if (widening_optab_handler (other_optab, mode, innermode) + if (find_widening_optab_handler (other_optab, mode, innermode, 0) != CODE_FOR_nothing && innermode == word_mode) { @@ -8619,6 +8635,64 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode, return temp; } + case COND_EXPR: + /* A COND_EXPR with its type being VOID_TYPE represents a + conditional jump and is handled in + expand_gimple_cond_expr. */ + gcc_assert (!VOID_TYPE_P (type)); + + /* Note that COND_EXPRs whose type is a structure or union + are required to be constructed to contain assignments of + a temporary variable, so that we can evaluate them here + for side effect only. If type is void, we must do likewise. */ + + gcc_assert (!TREE_ADDRESSABLE (type) + && !ignore + && TREE_TYPE (treeop1) != void_type_node + && TREE_TYPE (treeop2) != void_type_node); + + /* If we are not to produce a result, we have no target. Otherwise, + if a target was specified use it; it will not be used as an + intermediate target unless it is safe. If no target, use a + temporary. */ + + if (modifier != EXPAND_STACK_PARM + && original_target + && safe_from_p (original_target, treeop0, 1) + && GET_MODE (original_target) == mode +#ifdef HAVE_conditional_move + && (! can_conditionally_move_p (mode) + || REG_P (original_target)) +#endif + && !MEM_P (original_target)) + temp = original_target; + else + temp = assign_temp (type, 0, 0, 1); + + do_pending_stack_adjust (); + NO_DEFER_POP; + op0 = gen_label_rtx (); + op1 = gen_label_rtx (); + jumpifnot (treeop0, op0, -1); + store_expr (treeop1, temp, + modifier == EXPAND_STACK_PARM, + false); + + emit_jump_insn (gen_jump (op1)); + emit_barrier (); + emit_label (op0); + store_expr (treeop2, temp, + modifier == EXPAND_STACK_PARM, + false); + + emit_label (op1); + OK_DEFER_POP; + return temp; + + case VEC_COND_EXPR: + target = expand_vec_cond_expr (type, treeop0, treeop1, treeop2, target); + return target; + default: gcc_unreachable (); } @@ -9861,64 +9935,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, return op0; - case COND_EXPR: - /* A COND_EXPR with its type being VOID_TYPE represents a - conditional jump and is handled in - expand_gimple_cond_expr. */ - gcc_assert (!VOID_TYPE_P (type)); - - /* Note that COND_EXPRs whose type is a structure or union - are required to be constructed to contain assignments of - a temporary variable, so that we can evaluate them here - for side effect only. If type is void, we must do likewise. */ - - gcc_assert (!TREE_ADDRESSABLE (type) - && !ignore - && TREE_TYPE (treeop1) != void_type_node - && TREE_TYPE (treeop2) != void_type_node); - - /* If we are not to produce a result, we have no target. Otherwise, - if a target was specified use it; it will not be used as an - intermediate target unless it is safe. If no target, use a - temporary. */ - - if (modifier != EXPAND_STACK_PARM - && original_target - && safe_from_p (original_target, treeop0, 1) - && GET_MODE (original_target) == mode -#ifdef HAVE_conditional_move - && (! can_conditionally_move_p (mode) - || REG_P (original_target)) -#endif - && !MEM_P (original_target)) - temp = original_target; - else - temp = assign_temp (type, 0, 0, 1); - - do_pending_stack_adjust (); - NO_DEFER_POP; - op0 = gen_label_rtx (); - op1 = gen_label_rtx (); - jumpifnot (treeop0, op0, -1); - store_expr (treeop1, temp, - modifier == EXPAND_STACK_PARM, - false); - - emit_jump_insn (gen_jump (op1)); - emit_barrier (); - emit_label (op0); - store_expr (treeop2, temp, - modifier == EXPAND_STACK_PARM, - false); - - emit_label (op1); - OK_DEFER_POP; - return temp; - - case VEC_COND_EXPR: - target = expand_vec_cond_expr (type, treeop0, treeop1, treeop2, target); - return target; - case MODIFY_EXPR: { tree lhs = treeop0; @@ -10151,6 +10167,17 @@ string_constant (tree arg, tree *ptr_offset) fold_convert (sizetype, lower_bound)); } } + else if (TREE_CODE (TREE_OPERAND (arg, 0)) == MEM_REF) + { + array = TREE_OPERAND (TREE_OPERAND (arg, 0), 0); + offset = TREE_OPERAND (TREE_OPERAND (arg, 0), 1); + if (TREE_CODE (array) != ADDR_EXPR) + return 0; + array = TREE_OPERAND (array, 0); + if (TREE_CODE (array) != STRING_CST + && TREE_CODE (array) != VAR_DECL) + return 0; + } else return 0; }