#include "tree-dump.h"
#include "tree-pass.h"
#include "diagnostic-core.h"
-#include "toplev.h"
#include "except.h"
#include "cfgloop.h"
#include "cfglayout.h"
size_t i;
fold_stmt_inplace (stmt);
- if (cfgcleanup_altered_bbs)
+ if (cfgcleanup_altered_bbs && !is_gimple_debug (stmt))
bitmap_set_bit (cfgcleanup_altered_bbs, gimple_bb (stmt)->index);
/* FIXME. This should go in update_stmt. */
if (!POINTER_TYPE_P (TREE_TYPE (x))
|| !is_gimple_mem_ref_addr (x))
{
- error ("Invalid first operand of MEM_REF.");
+ error ("invalid first operand of MEM_REF");
return x;
}
if (TREE_CODE (TREE_OPERAND (t, 1)) != INTEGER_CST
|| !POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 1))))
{
- error ("Invalid offset operand of MEM_REF.");
+ error ("invalid offset operand of MEM_REF");
return TREE_OPERAND (t, 1);
}
if (TREE_CODE (x) == ADDR_EXPR
break;
case MODIFY_EXPR:
- error ("MODIFY_EXPR not expected while having tuples.");
+ error ("MODIFY_EXPR not expected while having tuples");
return *tp;
case ADDR_EXPR:
TREE_TYPE (TREE_OPERAND (t, 1))))
{
error ("invalid operand to pointer plus, second operand is not an "
- "integer with type of sizetype.");
+ "integer with type of sizetype");
return t;
}
/* FALLTHROUGH */
&& (TREE_CODE (op) == SSA_NAME
|| is_gimple_min_invariant (op)))
{
- error ("Conversion of an SSA_NAME on the left hand side.");
+ error ("conversion of an SSA_NAME on the left hand side");
debug_generic_stmt (expr);
return true;
}
else if (TREE_CODE (op) == SSA_NAME
&& TYPE_SIZE (TREE_TYPE (expr)) != TYPE_SIZE (TREE_TYPE (op)))
{
- error ("Conversion of register to a different size.");
+ error ("conversion of register to a different size");
debug_generic_stmt (expr);
return true;
}
{
if (!is_gimple_mem_ref_addr (TREE_OPERAND (expr, 0)))
{
- error ("Invalid address operand in MEM_REF.");
+ error ("invalid address operand in MEM_REF");
debug_generic_stmt (expr);
return true;
}
if (TREE_CODE (TREE_OPERAND (expr, 1)) != INTEGER_CST
|| !POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 1))))
{
- error ("Invalid offset operand in MEM_REF.");
+ error ("invalid offset operand in MEM_REF");
debug_generic_stmt (expr);
return true;
}
if (!TMR_BASE (expr)
|| !is_gimple_mem_ref_addr (TMR_BASE (expr)))
{
- error ("Invalid address operand in in TARGET_MEM_REF.");
+ error ("invalid address operand in in TARGET_MEM_REF");
return true;
}
if (!TMR_OFFSET (expr)
|| TREE_CODE (TMR_OFFSET (expr)) != INTEGER_CST
|| !POINTER_TYPE_P (TREE_TYPE (TMR_OFFSET (expr))))
{
- error ("Invalid offset operand in TARGET_MEM_REF.");
+ error ("invalid offset operand in TARGET_MEM_REF");
debug_generic_stmt (expr);
return true;
}
call, and the decl should have DECL_STATIC_CHAIN set. */
if (gimple_call_chain (stmt))
{
- if (TREE_CODE (fn) != ADDR_EXPR
- || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL)
+ if (!gimple_call_fndecl (stmt))
{
error ("static chain in indirect gimple call");
return true;
if (!DECL_STATIC_CHAIN (fn))
{
- error ("static chain with function that doesn't use one");
+ error ("static chain with function that doesn%'t use one");
return true;
}
}
{
error ("invalid argument to gimple call");
debug_generic_expr (arg);
+ return true;
}
}
}
break;
+ case FMA_EXPR:
+ if (!useless_type_conversion_p (lhs_type, rhs1_type)
+ || !useless_type_conversion_p (lhs_type, rhs2_type)
+ || !useless_type_conversion_p (lhs_type, rhs3_type))
+ {
+ error ("type mismatch in fused multiply-add expression");
+ debug_generic_expr (lhs_type);
+ debug_generic_expr (rhs1_type);
+ debug_generic_expr (rhs2_type);
+ debug_generic_expr (rhs3_type);
+ return true;
+ }
+ break;
+
default:
gcc_unreachable ();
}
return true;
}
- if (!types_compatible_p (TREE_TYPE (op), TREE_TYPE (TREE_TYPE (rhs1)))
+ /* Technically there is no longer a need for matching types, but
+ gimple hygiene asks for this check. In LTO we can end up
+ combining incompatible units and thus end up with addresses
+ of globals that change their type to a common one. */
+ if (!in_lto_p
+ && !types_compatible_p (TREE_TYPE (op),
+ TREE_TYPE (TREE_TYPE (rhs1)))
&& !one_pointer_to_useless_type_conversion_p (TREE_TYPE (rhs1),
TREE_TYPE (op)))
{
if (TREE_CODE (gimple_phi_result (stmt)) != SSA_NAME)
{
- error ("Invalid PHI result");
+ error ("invalid PHI result");
return true;
}
|| (!is_gimple_reg (gimple_phi_result (stmt))
&& !is_gimple_addressable (arg)))
{
- error ("Invalid PHI argument");
+ error ("invalid PHI argument");
debug_generic_stmt (arg);
return true;
}
if (!useless_type_conversion_p (type, TREE_TYPE (arg)))
{
- error ("Incompatible types in PHI argument %u", i);
+ error ("incompatible types in PHI argument %u", i);
debug_generic_stmt (type);
debug_generic_stmt (TREE_TYPE (arg));
return true;
if (!pointer_set_contains (visited, node->stmt))
{
- error ("Dead STMT in EH table");
+ error ("dead STMT in EH table");
debug_gimple_stmt (node->stmt);
eh_error_found = true;
}
{
def_operand_p def_p;
ssa_op_iter op_iter;
+ tree lhs;
stmt = gsi_stmt (gsi);
if (gimple_code (stmt) == GIMPLE_LABEL)
maybe_duplicate_eh_stmt (copy, stmt);
gimple_duplicate_stmt_histograms (cfun, copy, cfun, stmt);
+ /* When copying around a stmt writing into a local non-user
+ aggregate, make sure it won't share stack slot with other
+ vars. */
+ lhs = gimple_get_lhs (stmt);
+ if (lhs && TREE_CODE (lhs) != SSA_NAME)
+ {
+ tree base = get_base_address (lhs);
+ if (base
+ && (TREE_CODE (base) == VAR_DECL
+ || TREE_CODE (base) == RESULT_DECL)
+ && DECL_IGNORED_P (base)
+ && !TREE_STATIC (base)
+ && !DECL_EXTERNAL (base)
+ && (TREE_CODE (base) != VAR_DECL
+ || !DECL_HAS_VALUE_EXPR_P (base)))
+ DECL_NONSHAREABLE (base) = 1;
+ }
+
/* Create new names for all the definitions created by COPY and
add replacement mappings for each new name. */
FOR_EACH_SSA_DEF_OPERAND (def_p, copy, op_iter, SSA_OP_ALL_DEFS)
if (check_last_block)
{
basic_block bb = EXIT_BLOCK_PTR->prev_bb;
- gimple_stmt_iterator gsi = gsi_last_bb (bb);
+ gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb);
gimple t = NULL;
if (!gsi_end_p (gsi))
if (blocks && !TEST_BIT (blocks, i))
continue;
- gsi = gsi_last_bb (bb);
+ gsi = gsi_last_nondebug_bb (bb);
if (!gsi_end_p (gsi))
{
last_stmt = gsi_stmt (gsi);
return blocks_split;
}
-/* Purge dead abnormal call edges from basic block BB. */
-
-bool
-gimple_purge_dead_abnormal_call_edges (basic_block bb)
-{
- bool changed = gimple_purge_dead_eh_edges (bb);
-
- if (cfun->has_nonlocal_label)
- {
- gimple stmt = last_stmt (bb);
- edge_iterator ei;
- edge e;
-
- if (!(stmt && stmt_can_make_abnormal_goto (stmt)))
- for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
- {
- if (e->flags & EDGE_ABNORMAL)
- {
- remove_edge (e);
- changed = true;
- }
- else
- ei_next (&ei);
- }
-
- /* See gimple_purge_dead_eh_edges below. */
- if (changed)
- free_dominance_info (CDI_DOMINATORS);
- }
-
- return changed;
-}
-
/* Removes edge E and all the blocks dominated by it, and updates dominance
information. The IL in E->src needs to be updated separately.
If dominance info is not available, only the edge E is removed.*/
return changed;
}
+/* Purge dead EH edges from basic block listed in BLOCKS. */
+
bool
gimple_purge_all_dead_eh_edges (const_bitmap blocks)
{
return changed;
}
+/* Purge dead abnormal call edges from basic block BB. */
+
+bool
+gimple_purge_dead_abnormal_call_edges (basic_block bb)
+{
+ bool changed = false;
+ edge e;
+ edge_iterator ei;
+ gimple stmt = last_stmt (bb);
+
+ if (!cfun->has_nonlocal_label)
+ return false;
+
+ if (stmt && stmt_can_make_abnormal_goto (stmt))
+ return false;
+
+ for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
+ {
+ if (e->flags & EDGE_ABNORMAL)
+ {
+ remove_edge_and_dominated_blocks (e);
+ changed = true;
+ }
+ else
+ ei_next (&ei);
+ }
+
+ return changed;
+}
+
+/* Purge dead abnormal call edges from basic block listed in BLOCKS. */
+
+bool
+gimple_purge_all_dead_abnormal_call_edges (const_bitmap blocks)
+{
+ bool changed = false;
+ unsigned i;
+ bitmap_iterator bi;
+
+ EXECUTE_IF_SET_IN_BITMAP (blocks, 0, i, bi)
+ {
+ basic_block bb = BASIC_BLOCK (i);
+
+ /* Earlier gimple_purge_dead_abnormal_call_edges could have removed
+ this basic block already. */
+ gcc_assert (bb || changed);
+ if (bb != NULL)
+ changed |= gimple_purge_dead_abnormal_call_edges (bb);
+ }
+
+ return changed;
+}
+
/* This function is called whenever a new edge is created or
redirected. */
gimple_can_merge_blocks_p, /* can_merge_blocks_p */
gimple_merge_blocks, /* merge_blocks */
gimple_predict_edge, /* predict_edge */
- gimple_predicted_by_p, /* predicted_by_p */
+ gimple_predicted_by_p, /* predicted_by_p */
gimple_can_duplicate_bb_p, /* can_duplicate_block_p */
gimple_duplicate_bb, /* duplicate_block */
gimple_split_edge, /* split_edge */
NULL, /* tidy_fallthru_edge */
gimple_block_ends_with_call_p,/* block_ends_with_call_p */
gimple_block_ends_with_condjump_p, /* block_ends_with_condjump_p */
- gimple_flow_call_edges_add, /* flow_call_edges_add */
+ gimple_flow_call_edges_add, /* flow_call_edges_add */
gimple_execute_on_growing_pred, /* execute_on_growing_pred */
gimple_execute_on_shrinking_pred, /* execute_on_shrinking_pred */
gimple_duplicate_loop_to_header_edge, /* duplicate loop for trees */