X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fstmt.c;h=ad75392010b34235e9a1b85a094c825ed0a26f31;hb=29f9683a5f2242786773eaa8f066001a39f18c82;hp=9570f2504e43d4adef9ac4f38a970eea5897de78;hpb=c5d2e41c31f119b26d504a2f6232c831073f7d40;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/stmt.c b/gcc/stmt.c index 9570f2504e4..ad75392010b 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -1,6 +1,7 @@ /* Expands front end tree to back end RTL for GCC Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. This file is part of GCC. @@ -16,8 +17,8 @@ for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ +Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301, USA. */ /* This file handles the generation of rtl code from tree structure above the level of expressions, using subroutines in exp*.c and emit-rtl.c. @@ -30,6 +31,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "tm.h" #include "rtl.h" +#include "hard-reg-set.h" #include "tree.h" #include "tm_p.h" #include "flags.h" @@ -38,7 +40,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "insn-config.h" #include "expr.h" #include "libfuncs.h" -#include "hard-reg-set.h" #include "recog.h" #include "machmode.h" #include "toplev.h" @@ -110,7 +111,6 @@ static bool check_operand_nalternatives (tree, tree); static bool check_unique_operand_names (tree, tree); static char *resolve_operand_name_1 (char *, tree, tree); static void expand_null_return_1 (void); -static rtx shift_return_value (rtx); static void expand_value_return (rtx); static void do_jump_if_equal (rtx, rtx, rtx, int); static int estimate_case_costs (case_node_ptr); @@ -260,7 +260,7 @@ n_occurrences (int c, const char *s) or an ADDR_EXPR containing a STRING_CST. VOL nonzero means the insn is volatile; don't optimize it. */ -void +static void expand_asm (tree string, int vol) { rtx body; @@ -323,13 +323,13 @@ parse_output_constraint (const char **constraint_p, int operand_num, *is_inout = (*p == '+'); /* Canonicalize the output constraint so that it begins with `='. */ - if (p != constraint || is_inout) + if (p != constraint || *is_inout) { char *buf; size_t c_len = strlen (constraint); if (p != constraint) - warning ("output constraint %qc for operand %d " + warning (0, "output constraint %qc for operand %d " "is not at the beginning", *p, operand_num); @@ -553,20 +553,17 @@ parse_input_constraint (const char **constraint_p, int input_num, } if (saw_match && !*allows_reg) - warning ("matching constraint does not allow a register"); + warning (0, "matching constraint does not allow a register"); return true; } -/* Check for overlap between registers marked in CLOBBERED_REGS and - anything inappropriate in DECL. Emit error and return TRUE for error, - FALSE for ok. */ +/* Return true iff there's an overlap between REGS and DECL, where DECL + can be an asm-declared register. */ -static bool -decl_conflicts_with_clobbers_p (tree decl, const HARD_REG_SET clobbered_regs) +bool +decl_overlaps_hard_reg_set_p (tree decl, const HARD_REG_SET regs) { - /* Conflicts between asm-declared register variables and the clobber - list are not allowed. */ if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL) && DECL_REGISTER (decl) && REG_P (DECL_RTL (decl)) @@ -579,18 +576,34 @@ decl_conflicts_with_clobbers_p (tree decl, const HARD_REG_SET clobbered_regs) regno < (REGNO (reg) + hard_regno_nregs[REGNO (reg)][GET_MODE (reg)]); regno++) - if (TEST_HARD_REG_BIT (clobbered_regs, regno)) - { - error ("asm-specifier for variable %qs conflicts with " - "asm clobber list", - IDENTIFIER_POINTER (DECL_NAME (decl))); - - /* Reset registerness to stop multiple errors emitted for a - single variable. */ - DECL_REGISTER (decl) = 0; - return true; - } + if (TEST_HARD_REG_BIT (regs, regno)) + return true; } + + return false; +} + + +/* Check for overlap between registers marked in CLOBBERED_REGS and + anything inappropriate in DECL. Emit error and return TRUE for error, + FALSE for ok. */ + +static bool +decl_conflicts_with_clobbers_p (tree decl, const HARD_REG_SET clobbered_regs) +{ + /* Conflicts between asm-declared register variables and the clobber + list are not allowed. */ + if (decl_overlaps_hard_reg_set_p (decl, clobbered_regs)) + { + error ("asm-specifier for variable %qs conflicts with asm clobber list", + IDENTIFIER_POINTER (DECL_NAME (decl))); + + /* Reset registerness to stop multiple errors emitted for a single + variable. */ + DECL_REGISTER (decl) = 0; + return true; + } + return false; } @@ -611,7 +624,7 @@ decl_conflicts_with_clobbers_p (tree decl, const HARD_REG_SET clobbered_regs) VOL nonzero means the insn is volatile; don't optimize it. */ -void +static void expand_asm_operands (tree string, tree outputs, tree inputs, tree clobbers, int vol, location_t locus) { @@ -656,7 +669,7 @@ expand_asm_operands (tree string, tree outputs, tree inputs, Case in point is when the i386 backend moved from cc0 to a hard reg -- maintaining source-level compatibility means automatically clobbering the flags register. */ - clobbers = targetm.md_asm_clobbers (clobbers); + clobbers = targetm.md_asm_clobbers (outputs, inputs, clobbers); /* Count the number of meaningful clobbered registers, ignoring what we would ignore later. */ @@ -864,10 +877,10 @@ expand_asm_operands (tree string, tree outputs, tree inputs, if (asm_operand_ok (op, constraint) <= 0) { - if (allows_reg) + if (allows_reg && TYPE_MODE (type) != BLKmode) op = force_reg (TYPE_MODE (type), op); else if (!allows_mem) - warning ("asm operand %d probably doesn%'t match constraints", + warning (0, "asm operand %d probably doesn%'t match constraints", i + noutputs); else if (MEM_P (op)) { @@ -877,7 +890,7 @@ expand_asm_operands (tree string, tree outputs, tree inputs, } else { - warning ("use of memory input without lvalue in " + warning (0, "use of memory input without lvalue in " "asm operand %d is deprecated", i + noutputs); if (CONSTANT_P (op)) @@ -1360,7 +1373,7 @@ int warn_if_unused_value (tree exp, location_t locus) { restart: - if (TREE_USED (exp)) + if (TREE_USED (exp) || TREE_NO_WARNING (exp)) return 0; /* Don't warn about void constructs. This includes casting to void, @@ -1403,8 +1416,6 @@ warn_if_unused_value (tree exp, location_t locus) goto restart; case COMPOUND_EXPR: - if (TREE_NO_WARNING (exp)) - return 0; if (warn_if_unused_value (TREE_OPERAND (exp, 0), locus)) return 1; /* Let people do `(foo (), 0)' without a warning. */ @@ -1413,27 +1424,12 @@ warn_if_unused_value (tree exp, location_t locus) exp = TREE_OPERAND (exp, 1); goto restart; - case NOP_EXPR: - case CONVERT_EXPR: - case NON_LVALUE_EXPR: - /* Don't warn about conversions not explicit in the user's program. */ - if (TREE_NO_WARNING (exp)) + case COND_EXPR: + /* If this is an expression with side effects, don't warn; this + case commonly appears in macro expansions. */ + if (TREE_SIDE_EFFECTS (exp)) return 0; - /* Assignment to a cast usually results in a cast of a modify. - Don't complain about that. There can be an arbitrary number of - casts before the modify, so we must loop until we find the first - non-cast expression and then test to see if that is a modify. */ - { - tree tem = TREE_OPERAND (exp, 0); - - while (TREE_CODE (tem) == CONVERT_EXPR || TREE_CODE (tem) == NOP_EXPR) - tem = TREE_OPERAND (tem, 0); - - if (TREE_CODE (tem) == MODIFY_EXPR || TREE_CODE (tem) == INIT_EXPR - || TREE_CODE (tem) == CALL_EXPR) - return 0; - } - goto maybe_warn; + goto warn; case INDIRECT_REF: /* Don't warn about automatic dereferencing of references, since @@ -1457,12 +1453,8 @@ warn_if_unused_value (tree exp, location_t locus) if (EXPRESSION_CLASS_P (exp) && TREE_CODE_LENGTH (TREE_CODE (exp)) == 0) return 0; - maybe_warn: - /* If this is an expression with side effects, don't warn. */ - if (TREE_SIDE_EFFECTS (exp)) - return 0; - - warning ("%Hvalue computed is not used", &locus); + warn: + warning (0, "%Hvalue computed is not used", &locus); return 1; } } @@ -1500,33 +1492,6 @@ expand_naked_return (void) emit_jump (end_label); } -/* If the current function returns values in the most significant part - of a register, shift return value VAL appropriately. The mode of - the function's return type is known not to be BLKmode. */ - -static rtx -shift_return_value (rtx val) -{ - tree type; - - type = TREE_TYPE (DECL_RESULT (current_function_decl)); - if (targetm.calls.return_in_msb (type)) - { - rtx target; - HOST_WIDE_INT shift; - - target = DECL_RTL (DECL_RESULT (current_function_decl)); - shift = (GET_MODE_BITSIZE (GET_MODE (target)) - - BITS_PER_UNIT * int_size_in_bytes (type)); - if (shift > 0) - val = expand_shift (LSHIFT_EXPR, GET_MODE (target), - gen_lowpart (GET_MODE (target), val), - build_int_cst (NULL_TREE, shift), target, 1); - } - return val; -} - - /* Generate RTL to return from the current function, with value VAL. */ static void @@ -1564,15 +1529,9 @@ expand_value_return (rtx val) static void expand_null_return_1 (void) { - rtx end_label; - clear_pending_stack_adjust (); do_pending_stack_adjust (); - - end_label = return_label; - if (end_label == 0) - end_label = return_label = gen_label_rtx (); - emit_jump (end_label); + emit_jump (return_label); } /* Generate RTL to evaluate the expression RETVAL and return it @@ -1743,7 +1702,7 @@ expand_return (tree retval) val = expand_expr (retval_rhs, val, GET_MODE (val), 0); val = force_not_mem (val); /* Return the calculated value. */ - expand_value_return (shift_return_value (val)); + expand_value_return (val); } else { @@ -2258,10 +2217,10 @@ emit_case_bit_tests (tree index_type, tree index_expr, tree minval, else test[i].bits++; - lo = tree_low_cst (fold (build2 (MINUS_EXPR, index_type, - n->low, minval)), 1); - hi = tree_low_cst (fold (build2 (MINUS_EXPR, index_type, - n->high, minval)), 1); + lo = tree_low_cst (fold_build2 (MINUS_EXPR, index_type, + n->low, minval), 1); + hi = tree_low_cst (fold_build2 (MINUS_EXPR, index_type, + n->high, minval), 1); for (j = lo; j <= hi; j++) if (j >= HOST_BITS_PER_WIDE_INT) test[i].hi |= (HOST_WIDE_INT) 1 << (j - HOST_BITS_PER_INT); @@ -2271,9 +2230,9 @@ emit_case_bit_tests (tree index_type, tree index_expr, tree minval, qsort (test, count, sizeof(*test), case_bit_test_cmp); - index_expr = fold (build2 (MINUS_EXPR, index_type, - convert (index_type, index_expr), - convert (index_type, minval))); + index_expr = fold_build2 (MINUS_EXPR, index_type, + fold_convert (index_type, index_expr), + fold_convert (index_type, minval)); index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0); do_pending_stack_adjust (); @@ -2317,7 +2276,7 @@ expand_case (tree exp) { tree minval = NULL_TREE, maxval = NULL_TREE, range = NULL_TREE; rtx default_label = 0; - struct case_node *n, *m; + struct case_node *n; unsigned int count, uniq; rtx index; rtx table_label; @@ -2354,6 +2313,11 @@ expand_case (tree exp) if (index_type != error_mark_node) { tree elt; + bitmap label_bitmap; + + /* cleanup_tree_cfg removes all SWITCH_EXPR with their index + expressions being INTEGER_CST. */ + gcc_assert (TREE_CODE (index_expr) != INTEGER_CST); /* The default case is at the end of TREE_VEC. */ elt = TREE_VEC_ELT (vec, TREE_VEC_LENGTH (vec) - 1); @@ -2388,6 +2352,7 @@ expand_case (tree exp) uniq = 0; count = 0; + label_bitmap = BITMAP_ALLOC (NULL); for (n = case_list; n; n = n->right) { /* Count the elements and track the largest and smallest @@ -2408,38 +2373,42 @@ expand_case (tree exp) if (! tree_int_cst_equal (n->low, n->high)) count++; - /* Count the number of unique case node targets. */ - uniq++; + /* If we have not seen this label yet, then increase the + number of unique case node targets seen. */ lab = label_rtx (n->code_label); - for (m = case_list; m != n; m = m->right) - if (label_rtx (m->code_label) == lab) - { - uniq--; - break; - } + if (!bitmap_bit_p (label_bitmap, CODE_LABEL_NUMBER (lab))) + { + bitmap_set_bit (label_bitmap, CODE_LABEL_NUMBER (lab)); + uniq++; + } } - /* Compute span of values. */ - if (count != 0) - range = fold (build2 (MINUS_EXPR, index_type, maxval, minval)); + BITMAP_FREE (label_bitmap); + /* cleanup_tree_cfg removes all SWITCH_EXPR with a single + destination, such as one with a default case only. However, + it doesn't remove cases that are out of range for the switch + type, so we may still get a zero here. */ if (count == 0) { - expand_expr (index_expr, const0_rtx, VOIDmode, 0); emit_jump (default_label); + return; } + /* Compute span of values. */ + range = fold_build2 (MINUS_EXPR, index_type, maxval, minval); + /* Try implementing this switch statement by a short sequence of bit-wise comparisons. However, we let the binary-tree case below handle constant index expressions. */ - else if (CASE_USE_BIT_TESTS - && ! TREE_CONSTANT (index_expr) - && compare_tree_int (range, GET_MODE_BITSIZE (word_mode)) < 0 - && compare_tree_int (range, 0) > 0 - && lshift_cheap_p () - && ((uniq == 1 && count >= 3) - || (uniq == 2 && count >= 5) - || (uniq == 3 && count >= 6))) + if (CASE_USE_BIT_TESTS + && ! TREE_CONSTANT (index_expr) + && compare_tree_int (range, GET_MODE_BITSIZE (word_mode)) < 0 + && compare_tree_int (range, 0) > 0 + && lshift_cheap_p () + && ((uniq == 1 && count >= 3) + || (uniq == 2 && count >= 5) + || (uniq == 3 && count >= 6))) { /* Optimize the case where all the case values fit in a word without having to subtract MINVAL. In this case, @@ -2447,7 +2416,7 @@ expand_case (tree exp) if (compare_tree_int (minval, 0) > 0 && compare_tree_int (maxval, GET_MODE_BITSIZE (word_mode)) < 0) { - minval = integer_zero_node; + minval = build_int_cst (index_type, 0); range = maxval; } emit_case_bit_tests (index_type, index_expr, minval, range, @@ -2468,6 +2437,7 @@ expand_case (tree exp) #ifndef ASM_OUTPUT_ADDR_DIFF_ELT || flag_pic #endif + || !flag_jump_tables || TREE_CONSTANT (index_expr) /* If neither casesi or tablejump is available, we can only go this way. */ @@ -2497,58 +2467,26 @@ expand_case (tree exp) if (MEM_P (index)) index = copy_to_reg (index); - if (GET_CODE (index) == CONST_INT - || TREE_CODE (index_expr) == INTEGER_CST) - { - /* Make a tree node with the proper constant value - if we don't already have one. */ - if (TREE_CODE (index_expr) != INTEGER_CST) - { - index_expr - = build_int_cst_wide (NULL_TREE, INTVAL (index), - unsignedp || INTVAL (index) >= 0 - ? 0 : -1); - index_expr = convert (index_type, index_expr); - } - /* For constant index expressions we need only - issue an unconditional branch to the appropriate - target code. The job of removing any unreachable - code is left to the optimization phase if the - "-O" option is specified. */ - for (n = case_list; n; n = n->right) - if (! tree_int_cst_lt (index_expr, n->low) - && ! tree_int_cst_lt (n->high, index_expr)) - break; - - if (n) - emit_jump (label_rtx (n->code_label)); - else - emit_jump (default_label); - } - else - { - /* If the index expression is not constant we generate - a binary decision tree to select the appropriate - target code. This is done as follows: + /* We generate a binary decision tree to select the + appropriate target code. This is done as follows: - The list of cases is rearranged into a binary tree, - nearly optimal assuming equal probability for each case. + The list of cases is rearranged into a binary tree, + nearly optimal assuming equal probability for each case. - The tree is transformed into RTL, eliminating - redundant test conditions at the same time. + The tree is transformed into RTL, eliminating + redundant test conditions at the same time. - If program flow could reach the end of the - decision tree an unconditional jump to the - default code is emitted. */ + If program flow could reach the end of the + decision tree an unconditional jump to the + default code is emitted. */ - use_cost_table - = (TREE_CODE (orig_type) != ENUMERAL_TYPE - && estimate_case_costs (case_list)); - balance_case_nodes (&case_list, NULL); - emit_case_nodes (index, case_list, default_label, index_type); - emit_jump (default_label); - } + use_cost_table + = (TREE_CODE (orig_type) != ENUMERAL_TYPE + && estimate_case_costs (case_list)); + balance_case_nodes (&case_list, NULL); + emit_case_nodes (index, case_list, default_label, index_type); + emit_jump (default_label); } else { @@ -2557,7 +2495,6 @@ expand_case (tree exp) table_label, default_label)) { bool ok; - index_type = integer_type_node; /* Index jumptables from zero for suitable values of minval to avoid a subtraction. */ @@ -2565,7 +2502,7 @@ expand_case (tree exp) && compare_tree_int (minval, 0) > 0 && compare_tree_int (minval, 3) < 0) { - minval = integer_zero_node; + minval = build_int_cst (index_type, 0); range = maxval; } @@ -2586,11 +2523,11 @@ expand_case (tree exp) value since that should fit in a HOST_WIDE_INT while the actual values may not. */ HOST_WIDE_INT i_low - = tree_low_cst (fold (build2 (MINUS_EXPR, index_type, - n->low, minval)), 1); + = tree_low_cst (fold_build2 (MINUS_EXPR, index_type, + n->low, minval), 1); HOST_WIDE_INT i_high - = tree_low_cst (fold (build2 (MINUS_EXPR, index_type, - n->high, minval)), 1); + = tree_low_cst (fold_build2 (MINUS_EXPR, index_type, + n->high, minval), 1); HOST_WIDE_INT i; for (i = i_low; i <= i_high; i ++) @@ -2615,14 +2552,8 @@ expand_case (tree exp) emit_jump_insn (gen_rtx_ADDR_VEC (CASE_VECTOR_MODE, gen_rtvec_v (ncases, labelvec))); - /* If the case insn drops through the table, - after the table we must jump to the default-label. - Otherwise record no drop-through after the table. */ -#ifdef CASE_DROPS_THROUGH - emit_jump (default_label); -#else + /* Record no drop-through after the table. */ emit_barrier (); -#endif } before_case = NEXT_INSN (before_case); @@ -2679,8 +2610,7 @@ static int estimate_case_costs (case_node_ptr node) { tree min_ascii = integer_minus_one_node; - tree max_ascii = convert (TREE_TYPE (node->high), - build_int_cst (NULL_TREE, 127)); + tree max_ascii = build_int_cst (TREE_TYPE (node->high), 127); case_node_ptr n; int i; @@ -2878,8 +2808,9 @@ node_has_low_bound (case_node_ptr node, tree index_type) if (node->left) return 0; - low_minus_one = fold (build2 (MINUS_EXPR, TREE_TYPE (node->low), - node->low, integer_one_node)); + low_minus_one = fold_build2 (MINUS_EXPR, TREE_TYPE (node->low), + node->low, + build_int_cst (TREE_TYPE (node->low), 1)); /* If the subtraction above overflowed, we can't verify anything. Otherwise, look for a parent that tests our value - 1. */ @@ -2928,8 +2859,9 @@ node_has_high_bound (case_node_ptr node, tree index_type) if (node->right) return 0; - high_plus_one = fold (build2 (PLUS_EXPR, TREE_TYPE (node->high), - node->high, integer_one_node)); + high_plus_one = fold_build2 (PLUS_EXPR, TREE_TYPE (node->high), + node->high, + build_int_cst (TREE_TYPE (node->high), 1)); /* If the addition above overflowed, we can't verify anything. Otherwise, look for a parent that tests our value + 1. */ @@ -3109,11 +3041,12 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label, else if (node->right != 0 && node->left == 0) { - /* Here we have a right child but no left so we issue conditional + /* Here we have a right child but no left so we issue a conditional branch to default and process the right child. - Omit the conditional branch to default if we it avoid only one - right child; it costs too much space to save so little time. */ + Omit the conditional branch to default if the right child + does not have any children and is single valued; it would + cost too much space to save so little time. */ if (node->right->right || node->right->left || !tree_int_cst_equal (node->right->low, node->right->high)) @@ -3352,8 +3285,8 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label, new_index = expand_simple_binop (mode, MINUS, index, low_rtx, NULL_RTX, unsignedp, OPTAB_WIDEN); - new_bound = expand_expr (fold (build2 (MINUS_EXPR, type, - high, low)), + new_bound = expand_expr (fold_build2 (MINUS_EXPR, type, + high, low), NULL_RTX, mode, 0); emit_cmp_and_jump_insns (new_index, new_bound, GT, NULL_RTX,