All,

I have been debugging AVR port to see why we fail to match so many bit test opportunities.

When dealing with longer modes I have come across a problem I can not solve.

Expansion in RTL for a bit test can produce two styles.

STYLE 1 Bit to be tested is NOT LSB (e.g. if ( longthing & 0x10)), the expanded code contains the test as:

(and:SI (reg:SI 45 [ lx.1 ])
   (const_int 16 [0x10]))

Bit tests are matched by combine. Combine has no problems with this and eventually creates a matching pattern based on the conversion of the AND to a zero extraction

(set (pc)
   (if_then_else (ne (zero_extract:SI (subreg:QI (reg:SI 45 [ lx.1 ]) 0)
               (const_int 1 [0x1])
               (const_int 4 [0x4]))
           (const_int 0 [0x0]))
       (label_ref:HI 133)
       (pc)))

This will match Bit test patterns and produces optimal code. :-)

STYLE 2 Bit to be tested is LSB (e.g. if ( longthing & 1)), the expanded RTL code uses SUBREG to lower width (apparently from SImode to word size).

(and:HI (subreg:HI (reg:SI 45 [ lx.1 ]) 0)
   (const_int 1 [0x1]))

This seems to occur regardless of -f(no)split-wide-types for size > HImode (which is integer mode). This RTL becomes a problem for combine

Combine uses subst(), combine_simplify_rtx() and eventually simplify_comparison() where it attempts to WIDEN the AND and take the lowpart.

ge_low_part(HImode,
(and:SI (reg:SI 45 [ lx.1 ])
   (const_int 1 [0x1]))
)
However, gen_lowpart_for_combine() FAILS as it will reject taking lowpart of SImode expression because size>UNITS_PER_WORD.
So no test pattern can be  matched. :-(

Style 2 is hugely problematic. The substitution works fine, but the simplification will always fail - making it apparently impossible to create matching patterns for bit tests of the LSB of SImode or DImode values.

Any clues how I might get around this?

Andy






Reply via email to