------- Comment #3 from rguenth at gcc dot gnu dot org 2010-01-03 16:26 ------- Similar example not handled by bswap recognition:
typedef unsigned char u8; typedef unsigned int u32; union __anonunion { u32 value; u8 bytes[4]; }; u32 acpi_ut_dword_byte_swap (u32 value) { union __anonunion in; in.value = value; return (((((in.bytes[0] << 8) | in.bytes[1]) << 8) | in.bytes[2]) << 8) | in.bytes[3]; } here we also hit the recursion depth of the bswap recognition. Not so with typedef unsigned char u8; typedef unsigned int u32; union __anonunion { u32 value; u8 bytes[4]; }; u32 acpi_ut_dword_byte_swap (u32 value) { union __anonunion in; in.value = value; return (((in.bytes[0] << 8) | in.bytes[1]) << 16) | ((in.bytes[2] << 8) | in.bytes[3]); } but we do not handle # VUSE <.MEM_18> in$bytes$2_25 = in.bytes[2]; as bases (we probably could and it woudldn't be too hard - harder for the case with pointer arithmetic though). We end up trying with in$bytes$2_25 as base. Here: case BIT_IOR_EXPR: source_expr1 = find_bswap_1 (rhs1_stmt, &n1, limit - 1); if (!source_expr1) return NULL_TREE; source_expr2 = find_bswap_1 (rhs2_stmt, &n2, limit - 1); if (source_expr1 != source_expr2 || n1.size != n2.size) return NULL_TREE; we'd have to detect the source exprs common memory and adjust the piecewise symbolic numbers and create a common source expr. The idea would be to combine in.bytes[2] and in.bytes[3] to V_C_E <int> (in.bytes). As said it's going to me more complicated for accesses via pointers, *p, *(p+1), ... Note that once we extend this for memory we can as well do piecewise memory copy analysis and do store/load merging on the tree level. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42587