Hi! Ian reported a bug in optimize_range_tests_to_bit_test, high used to be off-by-one. E.g. if the topmost bit in mask is set (wi::clz (mask) is 0), then the highest number covered by the mask is lowi (which corresponds to bit 0) + prec - 1, rather than lowi + prec.
Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk as obvious. 2014-10-25 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/63641 * tree-ssa-reassoc.c (optimize_range_tests_to_bit_test): Set high to low + prec - 1 - clz (mask) instead of low + prec - clz (mask). * gcc.c-torture/execute/pr63641.c: New test. --- gcc/tree-ssa-reassoc.c.jj 2014-10-17 12:53:59.000000000 +0200 +++ gcc/tree-ssa-reassoc.c 2014-10-24 22:38:55.762859480 +0200 @@ -2513,7 +2513,7 @@ optimize_range_tests_to_bit_test (enum t { tree high = wide_int_to_tree (TREE_TYPE (lowi), wi::to_widest (lowi) - + prec - wi::clz (mask)); + + prec - 1 - wi::clz (mask)); operand_entry_t oe = (*ops)[ranges[i].idx]; tree op = oe->op; gimple stmt = op ? SSA_NAME_DEF_STMT (op) --- gcc/testsuite/gcc.c-torture/execute/pr63641.c.jj 2014-10-25 18:54:15.338191911 +0200 +++ gcc/testsuite/gcc.c-torture/execute/pr63641.c 2014-10-25 18:53:21.000000000 +0200 @@ -0,0 +1,54 @@ +/* PR tree-optimization/63641 */ + +__attribute__ ((noinline, noclone)) int +foo (unsigned char b) +{ + if (0x0 <= b && b <= 0x8) + goto lab; + if (b == 0x0b) + goto lab; + if (0x0e <= b && b <= 0x1a) + goto lab; + if (0x1c <= b && b <= 0x1f) + goto lab; + return 0; +lab: + return 1; +} + +__attribute__ ((noinline, noclone)) int +bar (unsigned char b) +{ + if (0x0 <= b && b <= 0x8) + goto lab; + if (b == 0x0b) + goto lab; + if (0x0e <= b && b <= 0x1a) + goto lab; + if (0x3c <= b && b <= 0x3f) + goto lab; + return 0; +lab: + return 1; +} + +char tab1[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1 }; +char tab2[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 }; + +int +main () +{ + int i; + asm volatile ("" : : : "memory"); + for (i = 0; i < 256; i++) + if (foo (i) != (i < 32 ? tab1[i] : 0)) + __builtin_abort (); + for (i = 0; i < 256; i++) + if (bar (i) != (i < 64 ? tab2[i] : 0)) + __builtin_abort (); + return 0; +} Jakub