From 45b0be94bed1f11918c43b420934eac6e2a11bf6 Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Tue, 12 Nov 2013 20:26:43 +0000 Subject: gimple-expr.h (create_tmp_var_name, [...]): Relocate prototypes from gimple.h. 2013-11-12 Andrew MacLeod * gimple-expr.h (create_tmp_var_name, create_tmp_var_raw, create_tmp_var, create_tmp_reg, mark_addressable, is_gimple_reg_rhs): Relocate prototypes from gimple.h. * gimplify.h: New File. Relocate some prototypes from gimple.h here. (gimple_predicate, enum fallback, enum gimplify_status): Relocate from gimple.h. * gimple.h: Move some prototypes to gimplify.h. (gimple_predicate, enum fallback, enum gimplify_status): Move to gimplify.h. (gimple_do_not_emit_location_p, gimple_set_do_not_emit_location): Relocate from gimpify.c. * gimple-expr.c (remove_suffix, tmp_var_id_num, create_tmp_var_name, create_tmp_var_raw, create_tmp_var, create_tmp_reg, mark_addressable, is_gimple_reg_rhs) Relocate from gimplify.c. * gimplify.c (mark_addressable): Move to gimple-expr.c. (gimple_seq_add_stmt_without_update): Move to gimple.c. (remove_suffix, tmp_var_id_num, create_tmp_var_name, create_tmp_var_raw, create_tmp_var, create_tmp_reg, is_gimple_reg_rhs): Move to gimple-expr.c. (should_carry_location_p): Move to gimple.c. (gimple_do_not_emit_location_p, gimple_set_do_not_emit_location): Move to gimple.h. (annotate_one_with_location, annotate_all_with_location_after, annotate_all_with_location): Move to gimple.c. (compare_case_labels, sort_case_labels, preprocess_case_label_vec_for_gimple): Move to gimple.c. (rhs_predicate_for): Make static. (gimplify_assign): Relocate from gimple.c. * gimple.c (gimplify_assign): Move to gimplify.c. (gimple_seq_add_stmt_without_update, should_carry_location_p, annotate_one_with_location, annotate_all_with_location_after, annotate_all_with_location, compare_case_labels, sort_case_labels, preprocess_case_label_vec_for_gimple): Relocate from gimplify.c. * tree.h (unshare_expr, unshare_expr_without_location, mark_addressable): Move prototypes to gimplify.h. * Makefile.in (GTFILES): gimple-expr.c now has the GTY tag for tmp_var_id_num * asan.c: Include gimplify.h rather than gimple.h. * cfgloopmanip.c: Likewise. * cgraphunit.c: Likewise. * cilk-common.c: Likewise. * dwarf2out.c: Dont include gimple.h. * fold-const.c: Include gimplify.h rather than gimple.h. * function.c: Likewise. * gimple-fold.c: Likewise. * gimple-ssa-strength-reduction.c: Likewise. * graphite-clast-to-gimple.c: Likewise. * graphite-sese-to-poly.c: Likewise. * ipa-prop.c: Likewise. * ipa-split.c: Likewise. * ipa.c: Likewise. * langhooks.c: Dont include gimple.h. * loop-init.c: Include gimplify.h rather than gimple.h. * omp-low.c: Likewise. * sese.c: Likewise. * stor-layout.c: Likewise. * targhooks.c: Likewise. * trans-mem.c: Likewise. * tree-affine.c: Likewise. * tree-cfg.c: Likewise. * tree-cfgcleanup.c: Likewise. * tree-complex.c: Likewise. * tree-if-conv.c: Likewise. * tree-inline.c: Likewise. * tree-iterator.c: Likewise. * tree-loop-distribution.c: Likewise. * tree-nested.c: Likewise. * tree-parloops.c: Likewise. * tree-predcom.c: Likewise. * tree-profile.c: Likewise. * tree-scalar-evolution.c: Likewise. * tree-sra.c: Likewise. * tree-ssa-address.c: Likewise. * tree-ssa-ccp.c: Likewise. * tree-ssa-dce.c: Likewise. * tree-ssa-forwprop.c: Likewise. * tree-ssa-ifcombine.c: Likewise. * tree-ssa-loop-im.c: Likewise. * tree-ssa-loop-ivopts.c: Likewise. * tree-ssa-loop-manip.c: Likewise. * tree-ssa-loop-niter.c: Likewise. * tree-ssa-loop-prefetch.c: Likewise. * tree-ssa-loop-unswitch.c: Likewise. * tree-ssa-math-opts.c: Likewise. * tree-ssa-phiopt.c: Likewise. * tree-ssa-phiprop.c: Likewise. * tree-ssa-pre.c: Likewise. * tree-ssa-propagate.c: Likewise. * tree-ssa-reassoc.c: Likewise. * tree-ssa-sccvn.c: Likewise. * tree-ssa-strlen.c: Likewise. * tree-ssa.c: Likewise. * tree-switch-conversio: Likewise.n.c * tree-tailcall.c: Likewise. * tree-vect-data-refs.c: Likewise. * tree-vect-generic.c: Likewise. * tree-vect-loop-manip.c: Likewise. * tree-vect-loop.c: Likewise. * tree-vect-patterns.c: Likewise. * tree-vect-stmts.c: Likewise. * tsan.c: Likewise. * value-prof.c: Likewise. * config/aarch64/aarch64.c: Include gimplify.h instead of gimple.h. * config/alpha/alpha.c: Likewise. * config/darwin.c: Likewise. * config/i386/i386.c: Likewise. * config/ia64/ia64.c: Likewise. * config/mep/mep.c: Likewise. * config/mips/mips.c: Likewise. * config/rs6000/rs6000.c: Likewise. * config/s390/s390.c: Likewise. * config/sh/sh.c: Likewise. * config/sparc/sparc.c: Likewise. * config/spu/spu.c: Likewise. * config/stormy16/stormy16.c: Likewise. * config/tilegx/tilegx.c: Likewise. * config/tilepro/tilepro.c: Likewise. * config/xtensa/xtensa.c: Likewise. * ada/gcc-interface/trans.c: Include gimplify.h. * c/c-typeck.c: Include gimplify.h. * c-family/c-common.c: Include gimplify.h. * c-family/c-gimplify.c: Likewise. * c-family/cilk.c: Likewise. * c-family/c-omp.c: Include gimple-expr.h instead of gimple.h. * c-family/c-ubsan.c: Don't include gimple.h. * cp/class.c: Include gimplify.h. * cp/cp-gimplify.c: Likewise. * cp/error.c: Likewise. * cp/init.c: Likewise. * cp/optimize.c: Likewise. * cp/pt.c: Likewise. * cp/semantics.c: Likewise. * cp/tree.c: Likewise. * cp/vtable-class-hierarchy.c: Likewise. * cp/decl2.c: Don't include gimple.h. * cp/except.c: Likewise. * cp/method.c: Include pointer-set.h instead of gimple.h. * fortran/f95-lang.c: Don't include gimple.h. * fortran/trans-array.c: Include gimple-expr.h instead of gimple.h. * fortran/trans.c: Likewise. * fortran/trans-decl.c: Likewise. * fortran/trans-expr.c: Include gimplify.h. * fortran/trans-openmp.c: Likewise. * go/go-lang.c: Include gimplify.h. * java/java-gimplify.c: Include gimplify.h. * objc/objc-act.c: Include gimplify.h. From-SVN: r204717 --- gcc/gimple.c | 296 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 278 insertions(+), 18 deletions(-) (limited to 'gcc/gimple.c') diff --git a/gcc/gimple.c b/gcc/gimple.c index 55dd09106bb..cba3bcedf54 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -29,6 +29,7 @@ along with GCC; see the file COPYING3. If not see #include "hard-reg-set.h" #include "basic-block.h" #include "gimple.h" +#include "gimplify.h" #include "diagnostic.h" #include "value-prof.h" #include "flags.h" @@ -446,24 +447,6 @@ gimple_build_assign_with_ops (enum tree_code subcode, tree lhs, tree op1, } -/* Build a new GIMPLE_ASSIGN tuple and append it to the end of *SEQ_P. - - DST/SRC are the destination and source respectively. You can pass - ungimplified trees in DST or SRC, in which case they will be - converted to a gimple operand if necessary. - - This function returns the newly created GIMPLE_ASSIGN tuple. */ - -gimple -gimplify_assign (tree dst, tree src, gimple_seq *seq_p) -{ - tree t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src); - gimplify_and_add (t, seq_p); - ggc_free (t); - return gimple_seq_last_stmt (*seq_p); -} - - /* Build a GIMPLE_COND statement. PRED is the condition used to compare LHS and the RHS. @@ -1172,6 +1155,23 @@ gimple_seq_add_stmt (gimple_seq *seq_p, gimple gs) gsi_insert_after (&si, gs, GSI_NEW_STMT); } +/* Link gimple statement GS to the end of the sequence *SEQ_P. If + *SEQ_P is NULL, a new sequence is allocated. This function is + similar to gimple_seq_add_stmt, but does not scan the operands. + During gimplification, we need to manipulate statement sequences + before the def/use vectors have been constructed. */ + +void +gimple_seq_add_stmt_without_update (gimple_seq *seq_p, gimple gs) +{ + gimple_stmt_iterator si; + + if (gs == NULL) + return; + + si = gsi_last (*seq_p); + gsi_insert_after_without_update (&si, gs, GSI_NEW_STMT); +} /* Append sequence SRC to the end of sequence *DST_P. If *DST_P is NULL, a new sequence is allocated. */ @@ -1187,6 +1187,64 @@ gimple_seq_add_seq (gimple_seq *dst_p, gimple_seq src) gsi_insert_seq_after (&si, src, GSI_NEW_STMT); } +/* Determine whether to assign a location to the statement GS. */ + +static bool +should_carry_location_p (gimple gs) +{ + /* Don't emit a line note for a label. We particularly don't want to + emit one for the break label, since it doesn't actually correspond + to the beginning of the loop/switch. */ + if (gimple_code (gs) == GIMPLE_LABEL) + return false; + + return true; +} + +/* Set the location for gimple statement GS to LOCATION. */ + +static void +annotate_one_with_location (gimple gs, location_t location) +{ + if (!gimple_has_location (gs) + && !gimple_do_not_emit_location_p (gs) + && should_carry_location_p (gs)) + gimple_set_location (gs, location); +} + +/* Set LOCATION for all the statements after iterator GSI in sequence + SEQ. If GSI is pointing to the end of the sequence, start with the + first statement in SEQ. */ + +void +annotate_all_with_location_after (gimple_seq seq, gimple_stmt_iterator gsi, + location_t location) +{ + if (gsi_end_p (gsi)) + gsi = gsi_start (seq); + else + gsi_next (&gsi); + + for (; !gsi_end_p (gsi); gsi_next (&gsi)) + annotate_one_with_location (gsi_stmt (gsi), location); +} + +/* Set the location for all the statements in a sequence STMT_P to LOCATION. */ + +void +annotate_all_with_location (gimple_seq stmt_p, location_t location) +{ + gimple_stmt_iterator i; + + if (gimple_seq_empty_p (stmt_p)) + return; + + for (i = gsi_start (stmt_p); !gsi_end_p (i); gsi_next (&i)) + { + gimple gs = gsi_stmt (i); + annotate_one_with_location (gs, location); + } +} /* Helper function of empty_body_p. Return true if STMT is an empty statement. */ @@ -3428,3 +3486,205 @@ infer_nonnull_range (gimple stmt, tree op) return false; } + +/* Compare two case labels. Because the front end should already have + made sure that case ranges do not overlap, it is enough to only compare + the CASE_LOW values of each case label. */ + +static int +compare_case_labels (const void *p1, const void *p2) +{ + const_tree const case1 = *(const_tree const*)p1; + const_tree const case2 = *(const_tree const*)p2; + + /* The 'default' case label always goes first. */ + if (!CASE_LOW (case1)) + return -1; + else if (!CASE_LOW (case2)) + return 1; + else + return tree_int_cst_compare (CASE_LOW (case1), CASE_LOW (case2)); +} + +/* Sort the case labels in LABEL_VEC in place in ascending order. */ + +void +sort_case_labels (vec label_vec) +{ + label_vec.qsort (compare_case_labels); +} + +/* Prepare a vector of case labels to be used in a GIMPLE_SWITCH statement. + + LABELS is a vector that contains all case labels to look at. + + INDEX_TYPE is the type of the switch index expression. Case labels + in LABELS are discarded if their values are not in the value range + covered by INDEX_TYPE. The remaining case label values are folded + to INDEX_TYPE. + + If a default case exists in LABELS, it is removed from LABELS and + returned in DEFAULT_CASEP. If no default case exists, but the + case labels already cover the whole range of INDEX_TYPE, a default + case is returned pointing to one of the existing case labels. + Otherwise DEFAULT_CASEP is set to NULL_TREE. + + DEFAULT_CASEP may be NULL, in which case the above comment doesn't + apply and no action is taken regardless of whether a default case is + found or not. */ + +void +preprocess_case_label_vec_for_gimple (vec labels, + tree index_type, + tree *default_casep) +{ + tree min_value, max_value; + tree default_case = NULL_TREE; + size_t i, len; + + i = 0; + min_value = TYPE_MIN_VALUE (index_type); + max_value = TYPE_MAX_VALUE (index_type); + while (i < labels.length ()) + { + tree elt = labels[i]; + tree low = CASE_LOW (elt); + tree high = CASE_HIGH (elt); + bool remove_element = FALSE; + + if (low) + { + gcc_checking_assert (TREE_CODE (low) == INTEGER_CST); + gcc_checking_assert (!high || TREE_CODE (high) == INTEGER_CST); + + /* This is a non-default case label, i.e. it has a value. + + See if the case label is reachable within the range of + the index type. Remove out-of-range case values. Turn + case ranges into a canonical form (high > low strictly) + and convert the case label values to the index type. + + NB: The type of gimple_switch_index() may be the promoted + type, but the case labels retain the original type. */ + + if (high) + { + /* This is a case range. Discard empty ranges. + If the bounds or the range are equal, turn this + into a simple (one-value) case. */ + int cmp = tree_int_cst_compare (high, low); + if (cmp < 0) + remove_element = TRUE; + else if (cmp == 0) + high = NULL_TREE; + } + + if (! high) + { + /* If the simple case value is unreachable, ignore it. */ + if ((TREE_CODE (min_value) == INTEGER_CST + && tree_int_cst_compare (low, min_value) < 0) + || (TREE_CODE (max_value) == INTEGER_CST + && tree_int_cst_compare (low, max_value) > 0)) + remove_element = TRUE; + else + low = fold_convert (index_type, low); + } + else + { + /* If the entire case range is unreachable, ignore it. */ + if ((TREE_CODE (min_value) == INTEGER_CST + && tree_int_cst_compare (high, min_value) < 0) + || (TREE_CODE (max_value) == INTEGER_CST + && tree_int_cst_compare (low, max_value) > 0)) + remove_element = TRUE; + else + { + /* If the lower bound is less than the index type's + minimum value, truncate the range bounds. */ + if (TREE_CODE (min_value) == INTEGER_CST + && tree_int_cst_compare (low, min_value) < 0) + low = min_value; + low = fold_convert (index_type, low); + + /* If the upper bound is greater than the index type's + maximum value, truncate the range bounds. */ + if (TREE_CODE (max_value) == INTEGER_CST + && tree_int_cst_compare (high, max_value) > 0) + high = max_value; + high = fold_convert (index_type, high); + + /* We may have folded a case range to a one-value case. */ + if (tree_int_cst_equal (low, high)) + high = NULL_TREE; + } + } + + CASE_LOW (elt) = low; + CASE_HIGH (elt) = high; + } + else + { + gcc_assert (!default_case); + default_case = elt; + /* The default case must be passed separately to the + gimple_build_switch routine. But if DEFAULT_CASEP + is NULL, we do not remove the default case (it would + be completely lost). */ + if (default_casep) + remove_element = TRUE; + } + + if (remove_element) + labels.ordered_remove (i); + else + i++; + } + len = i; + + if (!labels.is_empty ()) + sort_case_labels (labels); + + if (default_casep && !default_case) + { + /* If the switch has no default label, add one, so that we jump + around the switch body. If the labels already cover the whole + range of the switch index_type, add the default label pointing + to one of the existing labels. */ + if (len + && TYPE_MIN_VALUE (index_type) + && TYPE_MAX_VALUE (index_type) + && tree_int_cst_equal (CASE_LOW (labels[0]), + TYPE_MIN_VALUE (index_type))) + { + tree low, high = CASE_HIGH (labels[len - 1]); + if (!high) + high = CASE_LOW (labels[len - 1]); + if (tree_int_cst_equal (high, TYPE_MAX_VALUE (index_type))) + { + for (i = 1; i < len; i++) + { + high = CASE_LOW (labels[i]); + low = CASE_HIGH (labels[i - 1]); + if (!low) + low = CASE_LOW (labels[i - 1]); + if ((TREE_INT_CST_LOW (low) + 1 + != TREE_INT_CST_LOW (high)) + || (TREE_INT_CST_HIGH (low) + + (TREE_INT_CST_LOW (high) == 0) + != TREE_INT_CST_HIGH (high))) + break; + } + if (i == len) + { + tree label = CASE_LABEL (labels[0]); + default_case = build_case_label (NULL_TREE, NULL_TREE, + label); + } + } + } + } + + if (default_casep) + *default_casep = default_case; +} -- cgit v1.2.1