+2017-06-29 Richard Biener <rguenther@suse.de>
+
+ * tree-cfg.c (group_case_labels_stmt): Return whether we changed
+ anything.
+ (group_case_labels): Likewise.
+ (find_taken_edge): Push sanity checking on val to workers...
+ (find_taken_edge_cond_expr): ... here
+ (find_taken_edge_switch_expr): ... and here, handle cases
+ with just a default label.
+ * tree-cfg.h (group_case_labels_stmt): Adjust prototype.
+ (group_case_labels): Likewise.
+ * tree-cfgcleanup.c (execute_cleanup_cfg_post_optimizing): When
+ group_case_labels does anything cleanup the CFG again.
+
2017-06-29 Bin Cheng <bin.cheng@arm.com>
PR tree-optimization/81196
the ones jumping to the same label.
Eg. three separate entries 1: 2: 3: become one entry 1..3: */
-void
+bool
group_case_labels_stmt (gswitch *stmt)
{
int old_size = gimple_switch_num_labels (stmt);
gcc_assert (new_size <= old_size);
gimple_switch_set_num_labels (stmt, new_size);
+ return new_size < old_size;
}
/* Look for blocks ending in a multiway branch (a GIMPLE_SWITCH),
and scan the sorted vector of cases. Combine the ones jumping to the
same label. */
-void
+bool
group_case_labels (void)
{
basic_block bb;
+ bool changed = false;
FOR_EACH_BB_FN (bb, cfun)
{
gimple *stmt = last_stmt (bb);
if (stmt && gimple_code (stmt) == GIMPLE_SWITCH)
- group_case_labels_stmt (as_a <gswitch *> (stmt));
+ changed |= group_case_labels_stmt (as_a <gswitch *> (stmt));
}
+
+ return changed;
}
/* Checks whether we can merge block B into block A. */
stmt = last_stmt (bb);
- gcc_assert (stmt);
gcc_assert (is_ctrl_stmt (stmt));
- if (val == NULL)
- return NULL;
-
- if (!is_gimple_min_invariant (val))
- return NULL;
-
if (gimple_code (stmt) == GIMPLE_COND)
return find_taken_edge_cond_expr (bb, val);
It may be the case that we only need to allow the LABEL_REF to
appear inside an ADDR_EXPR, but we also allow the LABEL_REF to
appear inside a LABEL_EXPR just to be safe. */
- if ((TREE_CODE (val) == ADDR_EXPR || TREE_CODE (val) == LABEL_EXPR)
+ if (val
+ && (TREE_CODE (val) == ADDR_EXPR || TREE_CODE (val) == LABEL_EXPR)
&& TREE_CODE (TREE_OPERAND (val, 0)) == LABEL_DECL)
return find_taken_edge_computed_goto (bb, TREE_OPERAND (val, 0));
return NULL;
{
edge true_edge, false_edge;
+ if (val == NULL
+ || TREE_CODE (val) != INTEGER_CST)
+ return NULL;
+
extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
- gcc_assert (TREE_CODE (val) == INTEGER_CST);
return (integer_zerop (val) ? false_edge : true_edge);
}
edge e;
tree taken_case;
- taken_case = find_case_label_for_value (switch_stmt, val);
+ if (gimple_switch_num_labels (switch_stmt) == 1)
+ taken_case = gimple_switch_default_label (switch_stmt);
+ else if (! val || TREE_CODE (val) != INTEGER_CST)
+ return NULL;
+ else
+ taken_case = find_case_label_for_value (switch_stmt, val);
dest_bb = label_to_block (CASE_LABEL (taken_case));
e = find_edge (bb, dest_bb);
extern basic_block label_to_block_fn (struct function *, tree);
#define label_to_block(t) (label_to_block_fn (cfun, t))
extern void cleanup_dead_labels (void);
-extern void group_case_labels_stmt (gswitch *);
-extern void group_case_labels (void);
+extern bool group_case_labels_stmt (gswitch *);
+extern bool group_case_labels (void);
extern void replace_uses_by (tree, tree);
extern basic_block single_noncomplex_succ (basic_block bb);
extern void notice_special_calls (gcall *);