Hi! 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. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2022-05-31 Jakub Jelinek <ja...@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. --- gcc/tree-ssa-loop-unswitch.cc.jj 2022-05-25 11:07:29.754185772 +0200 +++ gcc/tree-ssa-loop-unswitch.cc 2022-05-30 10:57:23.165131441 +0200 @@ -494,6 +494,7 @@ find_unswitching_predicates_for_bb (basi { unsigned nlabels = gimple_switch_num_labels (stmt); tree idx = gimple_switch_index (stmt); + tree idx_type = TREE_TYPE (idx); if (TREE_CODE (idx) != SSA_NAME || nlabels < 1) return; @@ -526,16 +527,18 @@ find_unswitching_predicates_for_bb (basi 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)); } --- gcc/testsuite/gcc.dg/pr105770.c.jj 2022-05-30 11:08:30.603530499 +0200 +++ gcc/testsuite/gcc.dg/pr105770.c 2022-05-30 11:07:12.066406193 +0200 @@ -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 (); +} Jakub