Hi All, Here's a respin addressing review comments. Bootstrapped Regtested on aarch64-none-linux-gnu, x86_64-pc-linux-gnu and no issues. Ok for master? Thanks, Tamar gcc/ChangeLog: * match.pd: Add bitfield and shift folding. gcc/testsuite/ChangeLog: * gcc.dg/bitshift_1.c: New. * gcc.dg/bitshift_2.c: New. --- inline copy of patch --- diff --git a/gcc/match.pd b/gcc/match.pd index 70e90cdbfa902830e6b58be84e114e86ff7b4dff..a4ad465b2b074b21835be74732dce295f8db03bc 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -7245,6 +7245,45 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && ANY_INTEGRAL_TYPE_P (type) && ANY_INTEGRAL_TYPE_P (TREE_TYPE(@0))) (IFN_REDUC_PLUS_WIDEN @0))) +/* Canonicalize BIT_FIELD_REFS and right shift to BIT_FIELD_REFS. */ +(simplify + (rshift (BIT_FIELD_REF @0 @1 @2) INTEGER_CST@3) + (if (INTEGRAL_TYPE_P (type) + && tree_fits_uhwi_p (@1) + && tree_fits_uhwi_p (@3)) + (with { /* Can't use wide-int here as the precision differs between + @1 and @3. */ + unsigned HOST_WIDE_INT size = tree_to_uhwi (@1); + unsigned HOST_WIDE_INT shiftc = tree_to_uhwi (@3); + unsigned HOST_WIDE_INT newsize = size - shiftc; + tree nsize = wide_int_to_tree (bitsizetype, newsize); + tree ntype + = build_nonstandard_integer_type (newsize, TYPE_UNSIGNED (type)); } + (switch + (if (INTEGRAL_TYPE_P (ntype) && !BYTES_BIG_ENDIAN) + (convert:type (BIT_FIELD_REF:ntype @0 { nsize; } (plus @2 @3)))) + (if (INTEGRAL_TYPE_P (ntype) && BYTES_BIG_ENDIAN) + (convert:type (BIT_FIELD_REF:ntype @0 { nsize; } (minus @2 @3)))))))) + +/* Canonicalize BIT_FIELD_REFS and converts to BIT_FIELD_REFS. */ +(simplify + (convert (BIT_FIELD_REF@3 @0 @1 @2)) + (if (INTEGRAL_TYPE_P (type) + && INTEGRAL_TYPE_P (TREE_TYPE (@3))) + (with { unsigned int size_inner = element_precision (TREE_TYPE (@3)); + unsigned int size_outer = element_precision (type); } + (if (size_inner > size_outer) + /* Truncating convert, we can shrink the bit field similar to the + shift case. */ + (with { + tree nsize = wide_int_to_tree (bitsizetype, size_outer); + auto sign = TYPE_UNSIGNED (type); + tree ntype + = build_nonstandard_integer_type (size_outer, sign); + gcc_assert (useless_type_conversion_p (type, ntype)); } + (if (INTEGRAL_TYPE_P (ntype)) + (BIT_FIELD_REF:ntype @0 { nsize; } @2))))))) + (simplify (BIT_FIELD_REF (BIT_FIELD_REF @0 @1 @2) @3 @4) (BIT_FIELD_REF @0 @3 { const_binop (PLUS_EXPR, bitsizetype, @2, @4); })) diff --git a/gcc/testsuite/gcc.dg/bitshift_1.c b/gcc/testsuite/gcc.dg/bitshift_1.c new file mode 100644 index 0000000000000000000000000000000000000000..5995d0746d2301eb48304629cb4b779b079f1270 --- /dev/null +++ b/gcc/testsuite/gcc.dg/bitshift_1.c @@ -0,0 +1,50 @@ +/* { dg-do compile { target le } } */ +/* { dg-additional-options "-O2 -save-temps -fdump-tree-optimized" } */ + +typedef int v4si __attribute__ ((vector_size (16))); +typedef unsigned int v4usi __attribute__ ((vector_size (16))); +typedef unsigned short v8uhi __attribute__ ((vector_size (16))); + +unsigned int foor (v4usi x) +{ + return x[1] >> 16; +} +/* { dg-final { scan-tree-dump {BIT_FIELD_REF ;} "optimized" } } */ + +unsigned int fool (v4usi x) +{ + return x[1] << 16; +} +/* { dg-final { scan-tree-dump {BIT_FIELD_REF ;} "optimized" } } */ + +unsigned short foor2 (v4usi x) +{ + return x[3] >> 16; +} +/* { dg-final { scan-tree-dump {BIT_FIELD_REF ;} "optimized" } } */ + +unsigned int fool2 (v4usi x) +{ + return x[0] << 16; +} +/* { dg-final { scan-tree-dump {BIT_FIELD_REF ;} "optimized" } } */ + +unsigned char foor3 (v8uhi x) +{ + return x[3] >> 9; +} +/* { dg-final { scan-tree-dump {BIT_FIELD_REF ;} "optimized" } } */ + +unsigned short fool3 (v8uhi x) +{ + return x[0] << 9; +} +/* { dg-final { scan-tree-dump {BIT_FIELD_REF ;} "optimized" } } */ + +unsigned short foo2 (v4si x) +{ + int y = x[0] + x[1]; + return y >> 16; +} +/* { dg-final { scan-tree-dump {BIT_FIELD_REF ;} "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/bitshift_2.c b/gcc/testsuite/gcc.dg/bitshift_2.c new file mode 100644 index 0000000000000000000000000000000000000000..406b4def9d4aebbc83bd5bef92dab825b85f2aa4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/bitshift_2.c @@ -0,0 +1,49 @@ +/* { dg-do compile { target be } } */ +/* { dg-additional-options "-O2 -save-temps -fdump-tree-optimized" } */ + +typedef int v4si __attribute__ ((vector_size (16))); +typedef unsigned int v4usi __attribute__ ((vector_size (16))); +typedef unsigned short v8uhi __attribute__ ((vector_size (16))); + +unsigned int foor (v4usi x) +{ + return x[1] >> 16; +} +/* { dg-final { scan-tree-dump {BIT_FIELD_REF ;} "optimized" } } */ + +unsigned int fool (v4usi x) +{ + return x[1] << 16; +} +/* { dg-final { scan-tree-dump {BIT_FIELD_REF ;} "optimized" } } */ + +unsigned short foor2 (v4usi x) +{ + return x[3] >> 16; +} +/* { dg-final { scan-tree-dump {BIT_FIELD_REF ;} "optimized" } } */ + +unsigned int fool2 (v4usi x) +{ + return x[0] << 16; +} +/* { dg-final { scan-tree-dump {BIT_FIELD_REF ;} "optimized" } } */ + +unsigned char foor3 (v8uhi x) +{ + return x[3] >> 9; +} +/* { dg-final { scan-tree-dump {BIT_FIELD_REF ;} "optimized" } } */ + +unsigned short fool3 (v8uhi x) +{ + return x[0] << 9; +} +/* { dg-final { scan-tree-dump {BIT_FIELD_REF ;} "optimized" } } */ + +unsigned short foo2 (v4si x) +{ + int y = x[0] + x[1]; + return y >> 16; +} +/* { dg-final { scan-tree-dump {BIT_FIELD_REF ;} "optimized" } } */