unswitch: Fold case label lo/hi values to index type [PR105770]

The following testcase ICEs because we use different types in comparison,
idx has int type, while CASE_LOW has char type.

While I believe all CASE_{LOW,HIGH} in the same switch have to use the same
or compatible type, the index expression can have a promoted type as happens
in this testcase.  Other spots that handle switches do such foldings too.

2022-06-01  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/105770
	* tree-ssa-loop-unswitch.cc (find_unswitching_predicates_for_bb): Cast
	CASE_LOW and CASE_HIGH to TREE_TYPE (idx) before comparisons with idx.

	* gcc.dg/pr105770.c: New test.
This commit is contained in:
Jakub Jelinek 2022-06-01 14:00:49 +02:00
parent 45c8523dd3
commit 0d5cc976a3
2 changed files with 25 additions and 3 deletions

View File

@ -0,0 +1,19 @@
/* PR tree-optimization/105770 */
/* { dg-do compile } */
/* { dg-options "-O1 -funswitch-loops -fno-tree-forwprop" } */
char a;
void
foo (void)
{
while (a)
switch (a)
{
case ' ':
case '\t':
return;
}
__builtin_unreachable ();
}

View File

@ -494,6 +494,7 @@ find_unswitching_predicates_for_bb (basic_block bb, class loop *loop,
{
unsigned nlabels = gimple_switch_num_labels (stmt);
tree idx = gimple_switch_index (stmt);
tree idx_type = TREE_TYPE (idx);
if (!gimple_range_ssa_p (idx) || nlabels < 1)
return;
/* Index must be invariant. */
@ -525,16 +526,18 @@ find_unswitching_predicates_for_bb (basic_block bb, class loop *loop,
if (CASE_HIGH (lab) != NULL_TREE)
{
tree cmp1 = fold_build2 (GE_EXPR, boolean_type_node, idx,
CASE_LOW (lab));
fold_convert (idx_type,
CASE_LOW (lab)));
tree cmp2 = fold_build2 (LE_EXPR, boolean_type_node, idx,
CASE_HIGH (lab));
fold_convert (idx_type,
CASE_HIGH (lab)));
cmp = fold_build2 (BIT_AND_EXPR, boolean_type_node, cmp1, cmp2);
lab_range.set (CASE_LOW (lab), CASE_HIGH (lab));
}
else
{
cmp = fold_build2 (EQ_EXPR, boolean_type_node, idx,
CASE_LOW (lab));
fold_convert (idx_type, CASE_LOW (lab)));
lab_range.set (CASE_LOW (lab));
}