#include "stor-layout.h"
#include "print-tree.h"
#include "tm_p.h"
+#include "predict.h"
+#include "vec.h"
+#include "hashtab.h"
+#include "hash-set.h"
+#include "machmode.h"
+#include "hard-reg-set.h"
+#include "input.h"
+#include "function.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "cfganal.h"
#include "basic-block.h"
#include "flags.h"
-#include "function.h"
#include "gimple-pretty-print.h"
#include "tree-ssa-alias.h"
#include "internal-fn.h"
#include "gimplify-me.h"
#include "gimple-walk.h"
#include "gimple-ssa.h"
+#include "plugin-api.h"
+#include "ipa-ref.h"
#include "cgraph.h"
#include "tree-cfg.h"
#include "tree-phinodes.h"
discriminator_per_locus = NULL;
}
+/* Look for ANNOTATE calls with loop annotation kind in BB; if found, remove
+ them and propagate the information to LOOP. We assume that the annotations
+ come immediately before the condition in BB, if any. */
+
+static void
+replace_loop_annotate_in_block (basic_block bb, struct loop *loop)
+{
+ gimple_stmt_iterator gsi = gsi_last_bb (bb);
+ gimple stmt = gsi_stmt (gsi);
+
+ if (!(stmt && gimple_code (stmt) == GIMPLE_COND))
+ return;
+
+ for (gsi_prev_nondebug (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
+ {
+ stmt = gsi_stmt (gsi);
+ if (gimple_code (stmt) != GIMPLE_CALL)
+ break;
+ if (!gimple_call_internal_p (stmt)
+ || gimple_call_internal_fn (stmt) != IFN_ANNOTATE)
+ break;
+
+ switch ((annot_expr_kind) tree_to_shwi (gimple_call_arg (stmt, 1)))
+ {
+ case annot_expr_ivdep_kind:
+ loop->safelen = INT_MAX;
+ break;
+ case annot_expr_no_vector_kind:
+ loop->dont_vectorize = true;
+ break;
+ case annot_expr_vector_kind:
+ loop->force_vectorize = true;
+ cfun->has_force_vectorize_loops = true;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ stmt = gimple_build_assign (gimple_call_lhs (stmt),
+ gimple_call_arg (stmt, 0));
+ gsi_replace (&gsi, stmt, true);
+ }
+}
/* Look for ANNOTATE calls with loop annotation kind; if found, remove
them and propagate the information to the loop. We assume that the
annotations come immediately before the condition of the loop. */
static void
-replace_loop_annotate ()
+replace_loop_annotate (void)
{
struct loop *loop;
basic_block bb;
FOR_EACH_LOOP (loop, 0)
{
- gsi = gsi_last_bb (loop->header);
- stmt = gsi_stmt (gsi);
- if (!(stmt && gimple_code (stmt) == GIMPLE_COND))
- continue;
- for (gsi_prev_nondebug (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
- {
- stmt = gsi_stmt (gsi);
- if (gimple_code (stmt) != GIMPLE_CALL)
- break;
- if (!gimple_call_internal_p (stmt)
- || gimple_call_internal_fn (stmt) != IFN_ANNOTATE)
- break;
- switch ((annot_expr_kind) tree_to_shwi (gimple_call_arg (stmt, 1)))
- {
- case annot_expr_ivdep_kind:
- loop->safelen = INT_MAX;
- break;
- case annot_expr_no_vector_kind:
- loop->dont_vectorize = true;
- break;
- case annot_expr_vector_kind:
- loop->force_vectorize = true;
- cfun->has_force_vectorize_loops = true;
- break;
- default:
- gcc_unreachable ();
- }
- stmt = gimple_build_assign (gimple_call_lhs (stmt),
- gimple_call_arg (stmt, 0));
- gsi_replace (&gsi, stmt, true);
- }
+ /* First look into the header. */
+ replace_loop_annotate_in_block (loop->header, loop);
+
+ /* Then look into the latch, if any. */
+ if (loop->latch)
+ replace_loop_annotate_in_block (loop->latch, loop);
}
/* Remove IFN_ANNOTATE. Safeguard for the case loop->latch == NULL. */
{
stmt = gsi_stmt (gsi);
if (gimple_code (stmt) != GIMPLE_CALL)
- break;
+ continue;
if (!gimple_call_internal_p (stmt)
|| gimple_call_internal_fn (stmt) != IFN_ANNOTATE)
- break;
+ continue;
+
switch ((annot_expr_kind) tree_to_shwi (gimple_call_arg (stmt, 1)))
{
case annot_expr_ivdep_kind:
default:
gcc_unreachable ();
}
+
warning_at (gimple_location (stmt), 0, "ignoring loop annotation");
stmt = gimple_build_assign (gimple_call_lhs (stmt),
gimple_call_arg (stmt, 0));
return false;
}
- /* Protect the loop latches. */
- if (current_loops && b->loop_father->latch == b)
+ /* Protect simple loop latches. We only want to avoid merging
+ the latch with the loop header in this case. */
+ if (current_loops
+ && b->loop_father->latch == b
+ && loops_state_satisfies_p (LOOPS_HAVE_SIMPLE_LATCHES)
+ && b->loop_father->header == a)
return false;
/* It must be possible to eliminate all phi nodes in B. If ssa form
return false;
}
-
- case VEC_UNPACK_HI_EXPR:
- case VEC_UNPACK_LO_EXPR:
case REDUC_MAX_EXPR:
case REDUC_MIN_EXPR:
case REDUC_PLUS_EXPR:
+ if (!VECTOR_TYPE_P (rhs1_type)
+ || !useless_type_conversion_p (lhs_type, TREE_TYPE (rhs1_type)))
+ {
+ error ("reduction should convert from vector to element type");
+ debug_generic_expr (lhs_type);
+ debug_generic_expr (rhs1_type);
+ return true;
+ }
+ return false;
+
+ case VEC_UNPACK_HI_EXPR:
+ case VEC_UNPACK_LO_EXPR:
case VEC_UNPACK_FLOAT_HI_EXPR:
case VEC_UNPACK_FLOAT_LO_EXPR:
/* FIXME. */
case ABS_EXPR:
case BIT_NOT_EXPR:
case PAREN_EXPR:
- case NON_LVALUE_EXPR:
case CONJ_EXPR:
break;
return false;
}
- case VEC_LSHIFT_EXPR:
- case VEC_RSHIFT_EXPR:
- {
- if (TREE_CODE (rhs1_type) != VECTOR_TYPE
- || !(INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))
- || POINTER_TYPE_P (TREE_TYPE (rhs1_type))
- || FIXED_POINT_TYPE_P (TREE_TYPE (rhs1_type))
- || SCALAR_FLOAT_TYPE_P (TREE_TYPE (rhs1_type)))
- || (!INTEGRAL_TYPE_P (rhs2_type)
- && (TREE_CODE (rhs2_type) != VECTOR_TYPE
- || !INTEGRAL_TYPE_P (TREE_TYPE (rhs2_type))))
- || !useless_type_conversion_p (lhs_type, rhs1_type))
- {
- error ("type mismatch in vector shift expression");
- debug_generic_expr (lhs_type);
- debug_generic_expr (rhs1_type);
- debug_generic_expr (rhs2_type);
- return true;
- }
- /* For shifting a vector of non-integral components we
- only allow shifting by a constant multiple of the element size. */
- if (!INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))
- && (TREE_CODE (rhs2) != INTEGER_CST
- || !div_if_zero_remainder (rhs2,
- TYPE_SIZE (TREE_TYPE (rhs1_type)))))
- {
- error ("non-element sized vector shift of floating point vector");
- return true;
- }
-
- return false;
- }
-
case WIDEN_LSHIFT_EXPR:
{
if (!INTEGRAL_TYPE_P (lhs_type)
debug_generic_stmt (rhs1);
return true;
}
+ if (!is_gimple_val (elt_v))
+ {
+ error ("vector CONSTRUCTOR element is not a GIMPLE value");
+ debug_generic_stmt (rhs1);
+ return true;
+ }
}
}
+ else if (CONSTRUCTOR_NELTS (rhs1) != 0)
+ {
+ error ("non-vector CONSTRUCTOR with elements");
+ debug_generic_stmt (rhs1);
+ return true;
+ }
return res;
case OBJ_TYPE_REF:
case ASSERT_EXPR:
}
static bool eh_error_found;
-static int
-verify_eh_throw_stmt_node (void **slot, void *data)
+bool
+verify_eh_throw_stmt_node (const gimple &stmt, const int &,
+ hash_set<gimple> *visited)
{
- struct throw_stmt_node *node = (struct throw_stmt_node *)*slot;
- hash_set<void *> *visited = (hash_set<void *> *) data;
-
- if (!visited->contains (node->stmt))
+ if (!visited->contains (stmt))
{
error ("dead STMT in EH table");
- debug_gimple_stmt (node->stmt);
+ debug_gimple_stmt (stmt);
eh_error_found = true;
}
- return 1;
+ return true;
}
/* Verify if the location LOCs block is in BLOCKS. */
}
eh_error_found = false;
- if (get_eh_throw_stmt_table (cfun))
- htab_traverse (get_eh_throw_stmt_table (cfun),
- verify_eh_throw_stmt_node,
- &visited_stmts);
+ hash_map<gimple, int> *eh_table = get_eh_throw_stmt_table (cfun);
+ if (eh_table)
+ eh_table->traverse<hash_set<gimple> *, verify_eh_throw_stmt_node>
+ (&visited_stmts);
if (err || eh_error_found)
internal_error ("verify_gimple failed");
if (loops_for_fn (saved_cfun)->exits)
FOR_EACH_EDGE (e, ei, bb->succs)
{
- void **slot = htab_find_slot_with_hash
- (loops_for_fn (saved_cfun)->exits, e,
- htab_hash_pointer (e), NO_INSERT);
+ struct loops *l = loops_for_fn (saved_cfun);
+ loop_exit **slot
+ = l->exits->find_slot_with_hash (e, htab_hash_pointer (e),
+ NO_INSERT);
if (slot)
- htab_clear_slot (loops_for_fn (saved_cfun)->exits, slot);
+ l->exits->clear_slot (slot);
}
}
}
+/* Insert COND expression which is GIMPLE_COND after STMT
+ in basic block BB with appropriate basic block split
+ and creation of a new conditionally executed basic block.
+ Return created basic block. */
+basic_block
+insert_cond_bb (basic_block bb, gimple stmt, gimple cond)
+{
+ edge fall = split_block (bb, stmt);
+ gimple_stmt_iterator iter = gsi_last_bb (bb);
+ basic_block new_bb;
+
+ /* Insert cond statement. */
+ gcc_assert (gimple_code (cond) == GIMPLE_COND);
+ if (gsi_end_p (iter))
+ gsi_insert_before (&iter, cond, GSI_CONTINUE_LINKING);
+ else
+ gsi_insert_after (&iter, cond, GSI_CONTINUE_LINKING);
+
+ /* Create conditionally executed block. */
+ new_bb = create_empty_bb (bb);
+ make_edge (bb, new_bb, EDGE_TRUE_VALUE);
+ make_single_succ_edge (new_bb, fall->dest, EDGE_FALLTHRU);
+
+ /* Fix edge for split bb. */
+ fall->flags = EDGE_FALSE_VALUE;
+
+ /* Update dominance info. */
+ if (dom_info_available_p (CDI_DOMINATORS))
+ {
+ set_immediate_dominator (CDI_DOMINATORS, new_bb, bb);
+ set_immediate_dominator (CDI_DOMINATORS, fall->dest, bb);
+ }
+
+ /* Update loop info. */
+ if (current_loops)
+ add_bb_to_loop (new_bb, bb->loop_father);
+
+ return new_bb;
+}
+
/* Build a ternary operation and gimplify it. Emit code before GSI.
Return the gimple_val holding the result. */