diff options
Diffstat (limited to 'gcc/match.pd')
-rw-r--r-- | gcc/match.pd | 113 |
1 files changed, 103 insertions, 10 deletions
diff --git a/gcc/match.pd b/gcc/match.pd index 8de8858b151..e511e9a6b9b 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -685,11 +685,12 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) constants are involved. For example, convert (A | B) & (A | C) into A | (B & C) Further simplification will occur if B and C are constants. */ -(for op (bit_and bit_ior) - rop (bit_ior bit_and) +(for op (bit_and bit_ior bit_xor) + rop (bit_ior bit_and bit_and) (simplify - (op (convert? (rop:c @0 @1)) (convert? (rop @0 @2))) - (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) + (op (convert? (rop:c @0 @1)) (convert? (rop:c @0 @2))) + (if (tree_nop_conversion_p (type, TREE_TYPE (@1)) + && tree_nop_conversion_p (type, TREE_TYPE (@2))) (rop (convert @0) (op (convert @1) (convert @2)))))) @@ -787,12 +788,6 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (bitop:c (rbitop:c (bit_not @0) @1) @0) (bitop @0 @1))) -/* Simplify (A & B) OP0 (C & B) to (A OP0 C) & B. */ -(for bitop (bit_and bit_ior bit_xor) - (simplify - (bitop (bit_and:c @0 @1) (bit_and @2 @1)) - (bit_and (bitop @0 @2) @1))) - /* (x | CST1) & CST2 -> (x & CST2) | (CST1 & CST2) */ (simplify (bit_and (bit_ior @0 CONSTANT_CLASS_P@1) CONSTANT_CLASS_P@2) @@ -3234,3 +3229,101 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) WARN_STRICT_OVERFLOW_COMPARISON); } (cmp @0 { res; }))))))))) + +/* Canonicalizations of BIT_FIELD_REFs. */ + +(simplify + (BIT_FIELD_REF @0 @1 @2) + (switch + (if (TREE_CODE (TREE_TYPE (@0)) == COMPLEX_TYPE + && tree_int_cst_equal (@1, TYPE_SIZE (TREE_TYPE (TREE_TYPE (@0))))) + (switch + (if (integer_zerop (@2)) + (view_convert (realpart @0))) + (if (tree_int_cst_equal (@2, TYPE_SIZE (TREE_TYPE (TREE_TYPE (@0))))) + (view_convert (imagpart @0))))) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) + && INTEGRAL_TYPE_P (type) + /* On GIMPLE this should only apply to register arguments. */ + && (! GIMPLE || is_gimple_reg (@0)) + /* A bit-field-ref that referenced the full argument can be stripped. */ + && ((compare_tree_int (@1, TYPE_PRECISION (TREE_TYPE (@0))) == 0 + && integer_zerop (@2)) + /* Low-parts can be reduced to integral conversions. + ??? The following doesn't work for PDP endian. */ + || (BYTES_BIG_ENDIAN == WORDS_BIG_ENDIAN + /* Don't even think about BITS_BIG_ENDIAN. */ + && TYPE_PRECISION (TREE_TYPE (@0)) % BITS_PER_UNIT == 0 + && TYPE_PRECISION (type) % BITS_PER_UNIT == 0 + && compare_tree_int (@2, (BYTES_BIG_ENDIAN + ? (TYPE_PRECISION (TREE_TYPE (@0)) + - TYPE_PRECISION (type)) + : 0)) == 0))) + (convert @0)))) + +/* Simplify vector extracts. */ + +(simplify + (BIT_FIELD_REF CONSTRUCTOR@0 @1 @2) + (if (VECTOR_TYPE_P (TREE_TYPE (@0)) + && (types_match (type, TREE_TYPE (TREE_TYPE (@0))) + || (VECTOR_TYPE_P (type) + && types_match (TREE_TYPE (type), TREE_TYPE (TREE_TYPE (@0)))))) + (with + { + tree ctor = (TREE_CODE (@0) == SSA_NAME + ? gimple_assign_rhs1 (SSA_NAME_DEF_STMT (@0)) : @0); + tree eltype = TREE_TYPE (TREE_TYPE (ctor)); + unsigned HOST_WIDE_INT width = tree_to_uhwi (TYPE_SIZE (eltype)); + unsigned HOST_WIDE_INT n = tree_to_uhwi (@1); + unsigned HOST_WIDE_INT idx = tree_to_uhwi (@2); + } + (if (n != 0 + && (idx % width) == 0 + && (n % width) == 0 + && ((idx + n) / width) <= TYPE_VECTOR_SUBPARTS (TREE_TYPE (ctor))) + (with + { + idx = idx / width; + n = n / width; + /* Constructor elements can be subvectors. */ + unsigned HOST_WIDE_INT k = 1; + if (CONSTRUCTOR_NELTS (ctor) != 0) + { + tree cons_elem = TREE_TYPE (CONSTRUCTOR_ELT (ctor, 0)->value); + if (TREE_CODE (cons_elem) == VECTOR_TYPE) + k = TYPE_VECTOR_SUBPARTS (cons_elem); + } + } + (switch + /* We keep an exact subset of the constructor elements. */ + (if ((idx % k) == 0 && (n % k) == 0) + (if (CONSTRUCTOR_NELTS (ctor) == 0) + { build_constructor (type, NULL); } + (with + { + idx /= k; + n /= k; + } + (if (n == 1) + (if (idx < CONSTRUCTOR_NELTS (ctor)) + { CONSTRUCTOR_ELT (ctor, idx)->value; } + { build_zero_cst (type); }) + { + vec<constructor_elt, va_gc> *vals; + vec_alloc (vals, n); + for (unsigned i = 0; + i < n && idx + i < CONSTRUCTOR_NELTS (ctor); ++i) + CONSTRUCTOR_APPEND_ELT (vals, NULL_TREE, + CONSTRUCTOR_ELT (ctor, idx + i)->value); + build_constructor (type, vals); + })))) + /* The bitfield references a single constructor element. */ + (if (idx + n <= (idx / k + 1) * k) + (switch + (if (CONSTRUCTOR_NELTS (ctor) <= idx / k) + { build_zero_cst (type); }) + (if (n == k) + { CONSTRUCTOR_ELT (ctor, idx / k)->value; }) + (BIT_FIELD_REF { CONSTRUCTOR_ELT (ctor, idx / k)->value; } + @1 { bitsize_int ((idx % k) * width); }))))))))) |