Hi,
since the expansion of switches statement into decision trees was moved from
RTL to GIMPLE, the location information of the comparison statements has been
lost, i.e. GIMPLE generates comparison statements with UNKNOWN_LOCATION and
they are expanded as-is into RTL. Now this can be problematic for coverage
analysis because the statements can inherit a wrong location in the assembly.
Therefore the attached patch propagates the location from the switch statement
to every comparison statement generated for the decision tree.
Tested on x86_64-suse-linux, OK for mainline and 8 branch?
2018-11-16 Eric Botcazou <ebotca...@adacore.com>
* tree-switch-conversion.h (switch_decision_tree::emit_case_nodes): Add
location_t parameter.
(switch_decision_tree::emit_cmp_and_jump_insns): Likewise.
(switch_decision_tree::do_jump_if_equal): Likewise.
* tree-switch-conversion.c (switch_decision_tree::emit): Pass location
of switch statement to emit_case_nodes.
(switch_decision_tree::emit_cmp_and_jump_insns): Add LOC parameter and
set it on the newly built GIMPLE comparison statement.
(switch_decision_tree::do_jump_if_equal): Likewise.
(switch_decision_tree::emit_case_nodes): Add LOC parameter and pass it
into calls to do_jump_if_equal as well as recursive calls.
--
Eric Botcazou
Index: tree-switch-conversion.c
===================================================================
--- tree-switch-conversion.c (revision 266178)
+++ tree-switch-conversion.c (working copy)
@@ -1942,7 +1942,8 @@ switch_decision_tree::emit (basic_block
dump_case_nodes (dump_file, m_case_list, indent_step, 0);
}
- bb = emit_case_nodes (bb, index_expr, m_case_list, default_prob, index_type);
+ bb = emit_case_nodes (bb, index_expr, m_case_list, default_prob, index_type,
+ gimple_location (m_switch));
if (bb)
emit_jump (bb, m_default_bb);
@@ -2085,12 +2086,14 @@ basic_block
switch_decision_tree::emit_cmp_and_jump_insns (basic_block bb, tree op0,
tree op1, tree_code comparison,
basic_block label_bb,
- profile_probability prob)
+ profile_probability prob,
+ location_t loc)
{
// TODO: it's once called with lhs != index.
op1 = fold_convert (TREE_TYPE (op0), op1);
gcond *cond = gimple_build_cond (comparison, op0, op1, NULL_TREE, NULL_TREE);
+ gimple_set_location (cond, loc);
gimple_stmt_iterator gsi = gsi_last_bb (bb);
gsi_insert_after (&gsi, cond, GSI_NEW_STMT);
@@ -2114,11 +2117,13 @@ switch_decision_tree::emit_cmp_and_jump_
basic_block
switch_decision_tree::do_jump_if_equal (basic_block bb, tree op0, tree op1,
basic_block label_bb,
- profile_probability prob)
+ profile_probability prob,
+ location_t loc)
{
op1 = fold_convert (TREE_TYPE (op0), op1);
gcond *cond = gimple_build_cond (EQ_EXPR, op0, op1, NULL_TREE, NULL_TREE);
+ gimple_set_location (cond, loc);
gimple_stmt_iterator gsi = gsi_last_bb (bb);
gsi_insert_before (&gsi, cond, GSI_SAME_STMT);
@@ -2145,7 +2150,7 @@ basic_block
switch_decision_tree::emit_case_nodes (basic_block bb, tree index,
case_tree_node *node,
profile_probability default_prob,
- tree index_type)
+ tree index_type, location_t loc)
{
profile_probability p;
@@ -2160,7 +2165,7 @@ switch_decision_tree::emit_case_nodes (b
this node and then check our children, if any. */
p = node->m_c->m_prob / (node->m_c->m_subtree_prob + default_prob);
bb = do_jump_if_equal (bb, index, node->m_c->get_low (),
- node->m_c->m_case_bb, p);
+ node->m_c->m_case_bb, p, loc);
/* Since this case is taken at this point, reduce its weight from
subtree_weight. */
node->m_c->m_subtree_prob -= p;
@@ -2181,12 +2186,12 @@ switch_decision_tree::emit_case_nodes (b
p = (node->m_right->m_c->m_prob
/ (node->m_c->m_subtree_prob + default_prob));
bb = do_jump_if_equal (bb, index, node->m_right->m_c->get_low (),
- node->m_right->m_c->m_case_bb, p);
+ node->m_right->m_c->m_case_bb, p, loc);
p = (node->m_left->m_c->m_prob
/ (node->m_c->m_subtree_prob + default_prob));
bb = do_jump_if_equal (bb, index, node->m_left->m_c->get_low (),
- node->m_left->m_c->m_case_bb, p);
+ node->m_left->m_c->m_case_bb, p, loc);
}
else
{
@@ -2199,12 +2204,12 @@ switch_decision_tree::emit_case_nodes (b
+ default_prob.apply_scale (1, 2))
/ (node->m_c->m_subtree_prob + default_prob));
bb = emit_cmp_and_jump_insns (bb, index, node->m_c->get_high (),
- GT_EXPR, test_bb, p);
+ GT_EXPR, test_bb, p, loc);
default_prob = default_prob.apply_scale (1, 2);
/* Handle the left-hand subtree. */
bb = emit_case_nodes (bb, index, node->m_left,
- default_prob, index_type);
+ default_prob, index_type, loc);
/* If the left-hand subtree fell through,
don't let it fall into the right-hand subtree. */
@@ -2212,7 +2217,7 @@ switch_decision_tree::emit_case_nodes (b
emit_jump (bb, m_default_bb);
bb = emit_case_nodes (test_bb, index, node->m_right,
- default_prob, index_type);
+ default_prob, index_type, loc);
}
}
else if (node->m_left == NULL && node->m_right != NULL)
@@ -2232,11 +2237,11 @@ switch_decision_tree::emit_case_nodes (b
p = (default_prob.apply_scale (1, 2)
/ (node->m_c->m_subtree_prob + default_prob));
bb = emit_cmp_and_jump_insns (bb, index, node->m_c->get_low (),
- LT_EXPR, m_default_bb, p);
+ LT_EXPR, m_default_bb, p, loc);
default_prob = default_prob.apply_scale (1, 2);
bb = emit_case_nodes (bb, index, node->m_right, default_prob,
- index_type);
+ index_type, loc);
}
else
{
@@ -2246,7 +2251,7 @@ switch_decision_tree::emit_case_nodes (b
p = (node->m_right->m_c->m_subtree_prob
/ (node->m_c->m_subtree_prob + default_prob));
bb = do_jump_if_equal (bb, index, node->m_right->m_c->get_low (),
- node->m_right->m_c->m_case_bb, p);
+ node->m_right->m_c->m_case_bb, p, loc);
}
}
else if (node->m_left != NULL && node->m_right == NULL)
@@ -2259,11 +2264,11 @@ switch_decision_tree::emit_case_nodes (b
p = (default_prob.apply_scale (1, 2)
/ (node->m_c->m_subtree_prob + default_prob));
bb = emit_cmp_and_jump_insns (bb, index, node->m_c->get_high (),
- GT_EXPR, m_default_bb, p);
+ GT_EXPR, m_default_bb, p, loc);
default_prob = default_prob.apply_scale (1, 2);
bb = emit_case_nodes (bb, index, node->m_left, default_prob,
- index_type);
+ index_type, loc);
}
else
{
@@ -2273,7 +2278,7 @@ switch_decision_tree::emit_case_nodes (b
p = (node->m_left->m_c->m_subtree_prob
/ (node->m_c->m_subtree_prob + default_prob));
bb = do_jump_if_equal (bb, index, node->m_left->m_c->get_low (),
- node->m_left->m_c->m_case_bb, p);
+ node->m_left->m_c->m_case_bb, p, loc);
}
}
}
@@ -2297,17 +2302,17 @@ switch_decision_tree::emit_case_nodes (b
/ (node->m_c->m_subtree_prob + default_prob));
bb = emit_cmp_and_jump_insns (bb, index, node->m_c->get_high (),
- GT_EXPR, test_bb, p);
+ GT_EXPR, test_bb, p, loc);
default_prob = default_prob.apply_scale (1, 2);
/* Value belongs to this node or to the left-hand subtree. */
p = node->m_c->m_prob / (node->m_c->m_subtree_prob + default_prob);
bb = emit_cmp_and_jump_insns (bb, index, node->m_c->get_low (),
- GE_EXPR, node->m_c->m_case_bb, p);
+ GE_EXPR, node->m_c->m_case_bb, p, loc);
/* Handle the left-hand subtree. */
bb = emit_case_nodes (bb, index, node->m_left,
- default_prob, index_type);
+ default_prob, index_type, loc);
/* If the left-hand subtree fell through,
don't let it fall into the right-hand subtree. */
@@ -2315,7 +2320,7 @@ switch_decision_tree::emit_case_nodes (b
emit_jump (bb, m_default_bb);
bb = emit_case_nodes (test_bb, index, node->m_right,
- default_prob, index_type);
+ default_prob, index_type, loc);
}
else
{
@@ -2328,7 +2333,7 @@ switch_decision_tree::emit_case_nodes (b
p = default_prob / (node->m_c->m_subtree_prob + default_prob);
bb = emit_cmp_and_jump_insns (bb, lhs, rhs, GT_EXPR,
- m_default_bb, p);
+ m_default_bb, p, loc);
emit_jump (bb, node->m_c->m_case_bb);
return NULL;
Index: tree-switch-conversion.h
===================================================================
--- tree-switch-conversion.h (revision 266178)
+++ tree-switch-conversion.h (working copy)
@@ -566,7 +566,7 @@ struct switch_decision_tree
basic_block emit_case_nodes (basic_block bb, tree index,
case_tree_node *node,
profile_probability default_prob,
- tree index_type);
+ tree index_type, location_t);
/* Take an ordered list of case nodes
and transform them into a near optimal binary tree,
@@ -594,13 +594,15 @@ struct switch_decision_tree
static basic_block emit_cmp_and_jump_insns (basic_block bb, tree op0,
tree op1, tree_code comparison,
basic_block label_bb,
- profile_probability prob);
+ profile_probability prob,
+ location_t);
/* Generate code to jump to LABEL if OP0 and OP1 are equal in mode MODE.
PROB is the probability of jumping to LABEL_BB. */
static basic_block do_jump_if_equal (basic_block bb, tree op0, tree op1,
basic_block label_bb,
- profile_probability prob);
+ profile_probability prob,
+ location_t);
/* Reset the aux field of all outgoing edges of switch basic block. */
static inline void reset_out_edges_aux (gswitch *swtch);