GCC Middle and Back End API Reference
|
Data Fields | |
HOST_WIDE_INT | hi |
HOST_WIDE_INT | lo |
edge | target_edge |
tree | label |
int | bits |
@verbatim Implement switch statements with bit tests
A GIMPLE switch statement can be expanded to a short sequence of bit-wise comparisons. "switch(x)" is converted into "if ((1 << (x-MINVAL)) & CST)" where CST and MINVAL are integer constants. This is better than a series of compare-and-banch insns in some cases, e.g. we can implement:
if ((x==4) || (x==6) || (x==9) || (x==11))
as a single bit test:
if ((1<<x) & ((1<<4)|(1<<6)|(1<<9)|(1<<11)))
This transformation is only applied if the number of case targets is small, if CST constains at least 3 bits, and "1 << x" is cheap. The bit tests are performed in "word_mode".
The following example shows the code the transformation generates:
int bar(int x) { switch (x) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': return 1; } return 0; }
==>
bar (int x) { tmp1 = x - 48; if (tmp1 > (70 - 48)) goto L2; tmp2 = 1 << tmp1; tmp3 = 0b11111100000001111111111; if ((tmp2 & tmp3) != 0) goto L1 ; else goto L2; L1: return 1; L2: return 0; }
TODO: There are still some improvements to this transformation that could be implemented:
This transformation was contributed by Roger Sayle, see this e-mail: http://gcc.gnu.org/ml/gcc-patches/2003-01/msg01950.html
A case_bit_test represents a set of case nodes that may be selected from using a bit-wise comparison. HI and LO hold the integer to be tested against, TARGET_EDGE contains the edge to the basic block to jump to upon success and BITS counts the number of case nodes handled by this test, typically the number of bits set in HI:LO. The LABEL field is used to quickly identify all cases in this set without looking at label_to_block for every case label.
int case_bit_test::bits |
Referenced by case_bit_test_cmp(), and emit_case_bit_tests().
HOST_WIDE_INT case_bit_test::hi |
Referenced by emit_case_bit_tests().
tree case_bit_test::label |
Referenced by case_bit_test_cmp(), and emit_case_bit_tests().
HOST_WIDE_INT case_bit_test::lo |
Referenced by emit_case_bit_tests().
edge case_bit_test::target_edge |
Referenced by case_bit_test_cmp(), and emit_case_bit_tests().