aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/gcc/tree-cfg.c
diff options
context:
space:
mode:
authorRong Xu <xur@google.com>2014-07-21 23:47:22 (GMT)
committerRong Xu <xur@google.com>2014-07-29 22:31:03 (GMT)
commit38a8aecfb882072900434499696b5c32a2274515 (patch)
tree2aac97f0ae24b03cd98c1a06e989c031c173f889 /gcc-4.9/gcc/tree-cfg.c
parentc231900e5dcc14d8296bd9f62b45997a49d4d5e7 (diff)
downloadtoolchain_gcc-38a8aecfb882072900434499696b5c32a2274515.zip
toolchain_gcc-38a8aecfb882072900434499696b5c32a2274515.tar.gz
toolchain_gcc-38a8aecfb882072900434499696b5c32a2274515.tar.bz2
[4.9] Switch gcc-4.9 to use google/gcc-4_9 branch.
This source drop uses svn version r212828 of google/gcc-4.9 branch. We also cherry-picked r213062, r213063 and r213064 to fix windows build issues. All gcc-4.9 patches before July 3rd are ported to google/gcc-4.9. The following prior commits has not been merged to google branch yet. (They are included in this commit). e7af147f979e657fe2df00808e5b4319b0e088c6, baf87df3cb2683649ba7e9872362a7e721117c23, and c231900e5dcc14d8296bd9f62b45997a49d4d5e7. Change-Id: I4bea3ea470387ff751c2be4cb0d4a12059b9299b
Diffstat (limited to 'gcc-4.9/gcc/tree-cfg.c')
-rw-r--r--gcc-4.9/gcc/tree-cfg.c127
1 files changed, 118 insertions, 9 deletions
diff --git a/gcc-4.9/gcc/tree-cfg.c b/gcc-4.9/gcc/tree-cfg.c
index 56b6c35..d9896e7 100644
--- a/gcc-4.9/gcc/tree-cfg.c
+++ b/gcc-4.9/gcc/tree-cfg.c
@@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see
#include "tm_p.h"
#include "basic-block.h"
#include "flags.h"
+#include "input.h"
#include "function.h"
#include "gimple-pretty-print.h"
#include "pointer-set.h"
@@ -64,6 +65,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-propagate.h"
#include "value-prof.h"
#include "tree-inline.h"
+#include "l-ipo.h"
#include "target.h"
#include "tree-ssa-live.h"
#include "omp-low.h"
@@ -958,6 +960,32 @@ same_line_p (location_t locus1, location_t locus2)
&& filename_cmp (from.file, to.file) == 0);
}
+/* Assign a unique discriminator value to instructions in block BB that
+ have the same LOCUS as its predecessor block. */
+
+static void
+assign_discriminator (location_t locus, basic_block bb)
+{
+ gimple_stmt_iterator gsi;
+ int discriminator;
+
+ locus = map_discriminator_location (locus);
+
+ if (locus == UNKNOWN_LOCATION)
+ return;
+
+ discriminator = next_discriminator_for_locus (locus);
+
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple stmt = gsi_stmt (gsi);
+ location_t stmt_locus = gimple_location (stmt);
+ if (same_line_p (locus, stmt_locus))
+ gimple_set_location (stmt,
+ location_with_discriminator (stmt_locus, discriminator));
+ }
+}
+
/* Assign discriminators to each basic block. */
static void
@@ -969,8 +997,36 @@ assign_discriminators (void)
{
edge e;
edge_iterator ei;
+ gimple_stmt_iterator gsi;
gimple last = last_stmt (bb);
location_t locus = last ? gimple_location (last) : UNKNOWN_LOCATION;
+ location_t curr_locus = UNKNOWN_LOCATION;
+ int curr_discr = 0;
+
+ /* Traverse the basic block, if two function calls within a basic block
+ are mapped to a same line, assign a new discriminator because a call
+ stmt could be a split point of a basic block. */
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple stmt = gsi_stmt (gsi);
+ if (curr_locus == UNKNOWN_LOCATION)
+ {
+ curr_locus = gimple_location (stmt);
+ }
+ else if (!same_line_p (curr_locus, gimple_location (stmt)))
+ {
+ curr_locus = gimple_location (stmt);
+ curr_discr = 0;
+ }
+ else if (curr_discr != 0)
+ {
+ gimple_set_location (stmt, location_with_discriminator (
+ gimple_location (stmt), curr_discr));
+ }
+ /* Allocate a new discriminator for CALL stmt. */
+ if (gimple_code (stmt) == GIMPLE_CALL)
+ curr_discr = next_discriminator_for_locus (curr_locus);
+ }
if (locus == UNKNOWN_LOCATION)
continue;
@@ -982,10 +1038,12 @@ assign_discriminators (void)
if ((first && same_line_p (locus, gimple_location (first)))
|| (last && same_line_p (locus, gimple_location (last))))
{
- if (e->dest->discriminator != 0 && bb->discriminator == 0)
- bb->discriminator = next_discriminator_for_locus (locus);
+ if (((first && has_discriminator (gimple_location (first)))
+ || (last && has_discriminator (gimple_location (last))))
+ && !has_discriminator (locus))
+ assign_discriminator (locus, bb);
else
- e->dest->discriminator = next_discriminator_for_locus (locus);
+ assign_discriminator (locus, e->dest);
}
}
}
@@ -1864,6 +1922,15 @@ gimple_merge_blocks (basic_block a, basic_block b)
}
}
+ /* When merging two BBs, if their counts are different, the larger count
+ is selected as the new bb count. This is to handle inconsistent
+ profiles. */
+ if (a->loop_father == b->loop_father)
+ {
+ a->count = MAX (a->count, b->count);
+ a->frequency = MAX (a->frequency, b->frequency);
+ }
+
/* Merge the sequences. */
last = gsi_last_bb (a);
gsi_insert_seq_after (&last, bb_seq (b), GSI_NEW_STMT);
@@ -3032,7 +3099,8 @@ verify_types_in_gimple_reference (tree expr, bool require_lvalue)
/* Verify if the reference array element types are compatible. */
if (TREE_CODE (expr) == ARRAY_REF
&& !useless_type_conversion_p (TREE_TYPE (expr),
- TREE_TYPE (TREE_TYPE (op))))
+ TREE_TYPE (TREE_TYPE (op)))
+ && !L_IPO_COMP_MODE)
{
error ("type mismatch in array reference");
debug_generic_stmt (TREE_TYPE (expr));
@@ -3247,7 +3315,8 @@ verify_gimple_call (gimple stmt)
returning java.lang.Object.
For now simply allow arbitrary pointer type conversions. */
&& !(POINTER_TYPE_P (TREE_TYPE (gimple_call_lhs (stmt)))
- && POINTER_TYPE_P (TREE_TYPE (fntype))))
+ && POINTER_TYPE_P (TREE_TYPE (fntype)))
+ && !L_IPO_COMP_MODE)
{
error ("invalid conversion in gimple call");
debug_generic_stmt (TREE_TYPE (gimple_call_lhs (stmt)));
@@ -3946,6 +4015,36 @@ verify_gimple_assign_ternary (gimple stmt)
return false;
+ case SAD_EXPR:
+ if (!useless_type_conversion_p (rhs1_type, rhs2_type)
+ || !useless_type_conversion_p (lhs_type, rhs3_type)
+ || 2 * GET_MODE_BITSIZE (GET_MODE_INNER
+ (TYPE_MODE (TREE_TYPE (rhs1_type))))
+ > GET_MODE_BITSIZE (GET_MODE_INNER
+ (TYPE_MODE (TREE_TYPE (lhs_type)))))
+ {
+ error ("type mismatch in sad expression");
+ debug_generic_expr (lhs_type);
+ debug_generic_expr (rhs1_type);
+ debug_generic_expr (rhs2_type);
+ debug_generic_expr (rhs3_type);
+ return true;
+ }
+
+ if (TREE_CODE (rhs1_type) != VECTOR_TYPE
+ || TREE_CODE (rhs2_type) != VECTOR_TYPE
+ || TREE_CODE (rhs3_type) != VECTOR_TYPE)
+ {
+ error ("vector types expected in sad expression");
+ debug_generic_expr (lhs_type);
+ debug_generic_expr (rhs1_type);
+ debug_generic_expr (rhs2_type);
+ debug_generic_expr (rhs3_type);
+ return true;
+ }
+
+ return false;
+
case DOT_PROD_EXPR:
case REALIGN_LOAD_EXPR:
/* FIXME. */
@@ -3970,7 +4069,9 @@ verify_gimple_assign_single (gimple stmt)
tree rhs1_type = TREE_TYPE (rhs1);
bool res = false;
- if (!useless_type_conversion_p (lhs_type, rhs1_type))
+ if (!useless_type_conversion_p (lhs_type, rhs1_type)
+ /* Relax for LIPO. TODO add structural or name check. */
+ && !L_IPO_COMP_MODE)
{
error ("non-trivial conversion at assignment");
debug_generic_expr (lhs_type);
@@ -4214,7 +4315,8 @@ verify_gimple_return (gimple stmt)
&& DECL_BY_REFERENCE (SSA_NAME_VAR (op))))
op = TREE_TYPE (op);
- if (!useless_type_conversion_p (restype, TREE_TYPE (op)))
+ if (!useless_type_conversion_p (restype, TREE_TYPE (op))
+ && !L_IPO_COMP_MODE)
{
error ("invalid conversion in return statement");
debug_generic_stmt (restype);
@@ -5070,7 +5172,13 @@ gimple_verify_flow_info (void)
if (gimple_code (stmt) == GIMPLE_LABEL)
continue;
- err |= verify_eh_edges (stmt);
+ /* FIXME: there does seem to be an overassertion in eh
+ edge verification -- triggered by -fdyn-ipa: after eh
+ cleanup, there might not be an direct edge from a BB
+ to the parent try block's catch region, but the catch
+ region is still reachable. */
+ if (!flag_dyn_ipa)
+ err |= verify_eh_edges (stmt);
if (is_ctrl_stmt (stmt))
{
@@ -7476,7 +7584,8 @@ need_fake_edge_p (gimple t)
if (is_gimple_call (t)
&& fndecl
&& DECL_BUILT_IN (fndecl)
- && (call_flags & ECF_NOTHROW)
+ && ((call_flags & ECF_NOTHROW)
+ || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
&& !(call_flags & ECF_RETURNS_TWICE)
/* fork() doesn't really return twice, but the effect of
wrapping it in __gcov_fork() which calls __gcov_flush()