mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-27 23:41:29 +08:00
2014-11-09 Richard Biener <rguenther@suse.de> * match.pd: Add patterns convering two conversions in a row from fold-const.c. * fold-const.c (fold_unary_loc): Remove them here. * tree-ssa-forwprop.c (combine_conversions): Likewise. * genmatch.c (dt_node::gen_kids): Check whether we may follow SSA use-def chains. * g++.dg/cpp0x/constexpr-reinterpret1.C: XFAIL. * gcc.dg/tree-ssa/pr21031.c: XFAIL. From-SVN: r217260
415 lines
14 KiB
Plaintext
415 lines
14 KiB
Plaintext
/* Match-and-simplify patterns for shared GENERIC and GIMPLE folding.
|
|
This file is consumed by genmatch which produces gimple-match.c
|
|
and generic-match.c from it.
|
|
|
|
Copyright (C) 2014 Free Software Foundation, Inc.
|
|
Contributed by Richard Biener <rguenther@suse.de>
|
|
and Prathamesh Kulkarni <bilbotheelffriend@gmail.com>
|
|
|
|
This file is part of GCC.
|
|
|
|
GCC is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License as published by the Free
|
|
Software Foundation; either version 3, or (at your option) any later
|
|
version.
|
|
|
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with GCC; see the file COPYING3. If not see
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
|
|
/* Generic tree predicates we inherit. */
|
|
(define_predicates
|
|
integer_onep integer_zerop integer_all_onesp
|
|
real_zerop real_onep
|
|
CONSTANT_CLASS_P
|
|
tree_expr_nonnegative_p)
|
|
|
|
|
|
/* Simplifications of operations with one constant operand and
|
|
simplifications to constants or single values. */
|
|
|
|
(for op (plus pointer_plus minus bit_ior bit_xor)
|
|
(simplify
|
|
(op @0 integer_zerop)
|
|
(non_lvalue @0)))
|
|
|
|
/* 0 +p index -> (type)index */
|
|
(simplify
|
|
(pointer_plus integer_zerop @1)
|
|
(non_lvalue (convert @1)))
|
|
|
|
/* Simplify x - x.
|
|
This is unsafe for certain floats even in non-IEEE formats.
|
|
In IEEE, it is unsafe because it does wrong for NaNs.
|
|
Also note that operand_equal_p is always false if an operand
|
|
is volatile. */
|
|
(simplify
|
|
(minus @0 @0)
|
|
(if (!FLOAT_TYPE_P (type) || !HONOR_NANS (TYPE_MODE (type)))
|
|
{ build_zero_cst (type); }))
|
|
|
|
(simplify
|
|
(mult @0 integer_zerop@1)
|
|
@1)
|
|
|
|
/* Make sure to preserve divisions by zero. This is the reason why
|
|
we don't simplify x / x to 1 or 0 / x to 0. */
|
|
(for op (mult trunc_div ceil_div floor_div round_div exact_div)
|
|
(simplify
|
|
(op @0 integer_onep)
|
|
(non_lvalue @0)))
|
|
|
|
/* Same applies to modulo operations, but fold is inconsistent here
|
|
and simplifies 0 % x to 0, only preserving literal 0 % 0. */
|
|
(for op (ceil_mod floor_mod round_mod trunc_mod)
|
|
/* 0 % X is always zero. */
|
|
(simplify
|
|
(op integer_zerop@0 @1)
|
|
/* But not for 0 % 0 so that we can get the proper warnings and errors. */
|
|
(if (!integer_zerop (@1))
|
|
@0))
|
|
/* X % 1 is always zero. */
|
|
(simplify
|
|
(op @0 integer_onep)
|
|
{ build_zero_cst (type); }))
|
|
|
|
/* x | ~0 -> ~0 */
|
|
(simplify
|
|
(bit_ior @0 integer_all_onesp@1)
|
|
@1)
|
|
|
|
/* x & 0 -> 0 */
|
|
(simplify
|
|
(bit_and @0 integer_zerop@1)
|
|
@1)
|
|
|
|
/* x ^ x -> 0 */
|
|
(simplify
|
|
(bit_xor @0 @0)
|
|
{ build_zero_cst (type); })
|
|
|
|
/* Canonicalize X ^ ~0 to ~X. */
|
|
(simplify
|
|
(bit_xor @0 integer_all_onesp@1)
|
|
(bit_not @0))
|
|
|
|
/* x & ~0 -> x */
|
|
(simplify
|
|
(bit_and @0 integer_all_onesp)
|
|
(non_lvalue @0))
|
|
|
|
/* x & x -> x, x | x -> x */
|
|
(for bitop (bit_and bit_ior)
|
|
(simplify
|
|
(bitop @0 @0)
|
|
(non_lvalue @0)))
|
|
|
|
(simplify
|
|
(abs (negate @0))
|
|
(abs @0))
|
|
(simplify
|
|
(abs tree_expr_nonnegative_p@0)
|
|
@0)
|
|
|
|
|
|
/* Try to fold (type) X op CST -> (type) (X op ((type-x) CST))
|
|
when profitable.
|
|
For bitwise binary operations apply operand conversions to the
|
|
binary operation result instead of to the operands. This allows
|
|
to combine successive conversions and bitwise binary operations.
|
|
We combine the above two cases by using a conditional convert. */
|
|
(for bitop (bit_and bit_ior bit_xor)
|
|
(simplify
|
|
(bitop (convert @0) (convert? @1))
|
|
(if (((TREE_CODE (@1) == INTEGER_CST
|
|
&& INTEGRAL_TYPE_P (TREE_TYPE (@0))
|
|
&& int_fits_type_p (@1, TREE_TYPE (@0)))
|
|
|| (GIMPLE && types_compatible_p (TREE_TYPE (@0), TREE_TYPE (@1)))
|
|
|| (GENERIC && TREE_TYPE (@0) == TREE_TYPE (@1)))
|
|
/* ??? This transform conflicts with fold-const.c doing
|
|
Convert (T)(x & c) into (T)x & (T)c, if c is an integer
|
|
constants (if x has signed type, the sign bit cannot be set
|
|
in c). This folds extension into the BIT_AND_EXPR.
|
|
Restrict it to GIMPLE to avoid endless recursions. */
|
|
&& (bitop != BIT_AND_EXPR || GIMPLE)
|
|
&& (/* That's a good idea if the conversion widens the operand, thus
|
|
after hoisting the conversion the operation will be narrower. */
|
|
TYPE_PRECISION (TREE_TYPE (@0)) < TYPE_PRECISION (type)
|
|
/* It's also a good idea if the conversion is to a non-integer
|
|
mode. */
|
|
|| GET_MODE_CLASS (TYPE_MODE (type)) != MODE_INT
|
|
/* Or if the precision of TO is not the same as the precision
|
|
of its mode. */
|
|
|| TYPE_PRECISION (type) != GET_MODE_PRECISION (TYPE_MODE (type))))
|
|
(convert (bitop @0 (convert @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)
|
|
(bit_ior (bit_and @0 @2) (bit_and @1 @2)))
|
|
|
|
/* Combine successive equal operations with constants. */
|
|
(for bitop (bit_and bit_ior bit_xor)
|
|
(simplify
|
|
(bitop (bitop @0 CONSTANT_CLASS_P@1) CONSTANT_CLASS_P@2)
|
|
(bitop @0 (bitop @1 @2))))
|
|
|
|
/* Try simple folding for X op !X, and X op X with the help
|
|
of the truth_valued_p and logical_inverted_value predicates. */
|
|
(match truth_valued_p
|
|
@0
|
|
(if (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) == 1)))
|
|
(for op (lt le eq ne ge gt truth_and truth_andif truth_or truth_orif truth_xor)
|
|
(match truth_valued_p
|
|
(op @0 @1)))
|
|
(match truth_valued_p
|
|
(truth_not @0))
|
|
|
|
(match (logical_inverted_value @0)
|
|
(bit_not truth_valued_p@0))
|
|
(match (logical_inverted_value @0)
|
|
(eq @0 integer_zerop)
|
|
(if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))))
|
|
(match (logical_inverted_value @0)
|
|
(ne truth_valued_p@0 integer_onep)
|
|
(if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))))
|
|
(match (logical_inverted_value @0)
|
|
(bit_xor truth_valued_p@0 integer_onep))
|
|
|
|
/* X & !X -> 0. */
|
|
(simplify
|
|
(bit_and:c @0 (logical_inverted_value @0))
|
|
{ build_zero_cst (type); })
|
|
/* X | !X and X ^ !X -> 1, , if X is truth-valued. */
|
|
(for op (bit_ior bit_xor)
|
|
(simplify
|
|
(op:c truth_valued_p@0 (logical_inverted_value @0))
|
|
{ build_one_cst (type); }))
|
|
|
|
(for bitop (bit_and bit_ior)
|
|
rbitop (bit_ior bit_and)
|
|
/* (x | y) & x -> x */
|
|
/* (x & y) | x -> x */
|
|
(simplify
|
|
(bitop:c (rbitop:c @0 @1) @0)
|
|
@0)
|
|
/* (~x | y) & x -> x & y */
|
|
/* (~x & y) | x -> x | y */
|
|
(simplify
|
|
(bitop:c (rbitop:c (bit_not @0) @1) @0)
|
|
(bitop @0 @1)))
|
|
|
|
/* If arg1 and arg2 are booleans (or any single bit type)
|
|
then try to simplify:
|
|
|
|
(~X & Y) -> X < Y
|
|
(X & ~Y) -> Y < X
|
|
(~X | Y) -> X <= Y
|
|
(X | ~Y) -> Y <= X
|
|
|
|
But only do this if our result feeds into a comparison as
|
|
this transformation is not always a win, particularly on
|
|
targets with and-not instructions.
|
|
-> simplify_bitwise_binary_boolean */
|
|
(simplify
|
|
(ne (bit_and:c (bit_not @0) @1) integer_zerop)
|
|
(if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
|
|
&& TYPE_PRECISION (TREE_TYPE (@1)) == 1)
|
|
(lt @0 @1)))
|
|
(simplify
|
|
(ne (bit_ior:c (bit_not @0) @1) integer_zerop)
|
|
(if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
|
|
&& TYPE_PRECISION (TREE_TYPE (@1)) == 1)
|
|
(le @0 @1)))
|
|
|
|
/* ~~x -> x */
|
|
(simplify
|
|
(bit_not (bit_not @0))
|
|
@0)
|
|
|
|
(simplify
|
|
(negate (negate @0))
|
|
@0)
|
|
|
|
|
|
/* Associate (p +p off1) +p off2 as (p +p (off1 + off2)). */
|
|
(simplify
|
|
(pointer_plus (pointer_plus @0 @1) @3)
|
|
(pointer_plus @0 (plus @1 @3)))
|
|
|
|
/* Pattern match
|
|
tem1 = (long) ptr1;
|
|
tem2 = (long) ptr2;
|
|
tem3 = tem2 - tem1;
|
|
tem4 = (unsigned long) tem3;
|
|
tem5 = ptr1 + tem4;
|
|
and produce
|
|
tem5 = ptr2; */
|
|
(simplify
|
|
(pointer_plus @0 (convert?@2 (minus@3 (convert @1) (convert @0))))
|
|
/* Conditionally look through a sign-changing conversion. */
|
|
(if (TYPE_PRECISION (TREE_TYPE (@2)) == TYPE_PRECISION (TREE_TYPE (@3))
|
|
&& ((GIMPLE && useless_type_conversion_p (type, TREE_TYPE (@1)))
|
|
|| (GENERIC && type == TREE_TYPE (@1))))
|
|
@1))
|
|
|
|
/* Pattern match
|
|
tem = (sizetype) ptr;
|
|
tem = tem & algn;
|
|
tem = -tem;
|
|
... = ptr p+ tem;
|
|
and produce the simpler and easier to analyze with respect to alignment
|
|
... = ptr & ~algn; */
|
|
(simplify
|
|
(pointer_plus @0 (negate (bit_and (convert @0) INTEGER_CST@1)))
|
|
(with { tree algn = wide_int_to_tree (TREE_TYPE (@0), wi::bit_not (@1)); }
|
|
(bit_and @0 { algn; })))
|
|
|
|
|
|
/* Simplifications of conversions. */
|
|
|
|
/* Basic strip-useless-type-conversions / strip_nops. */
|
|
(for cvt (convert view_convert float fix_trunc)
|
|
(simplify
|
|
(cvt @0)
|
|
(if ((GIMPLE && useless_type_conversion_p (type, TREE_TYPE (@0)))
|
|
|| (GENERIC && type == TREE_TYPE (@0)))
|
|
@0)))
|
|
|
|
/* Contract view-conversions. */
|
|
(simplify
|
|
(view_convert (view_convert @0))
|
|
(view_convert @0))
|
|
|
|
/* For integral conversions with the same precision or pointer
|
|
conversions use a NOP_EXPR instead. */
|
|
(simplify
|
|
(view_convert @0)
|
|
(if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
|
|
&& (INTEGRAL_TYPE_P (TREE_TYPE (@0)) || POINTER_TYPE_P (TREE_TYPE (@0)))
|
|
&& TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (@0)))
|
|
(convert @0)))
|
|
|
|
/* Strip inner integral conversions that do not change precision or size. */
|
|
(simplify
|
|
(view_convert (convert@0 @1))
|
|
(if ((INTEGRAL_TYPE_P (TREE_TYPE (@0)) || POINTER_TYPE_P (TREE_TYPE (@0)))
|
|
&& (INTEGRAL_TYPE_P (TREE_TYPE (@1)) || POINTER_TYPE_P (TREE_TYPE (@1)))
|
|
&& (TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (TREE_TYPE (@1)))
|
|
&& (TYPE_SIZE (TREE_TYPE (@0)) == TYPE_SIZE (TREE_TYPE (@1))))
|
|
(view_convert @1)))
|
|
|
|
/* Re-association barriers around constants and other re-association
|
|
barriers can be removed. */
|
|
(simplify
|
|
(paren CONSTANT_CLASS_P@0)
|
|
@0)
|
|
(simplify
|
|
(paren (paren@1 @0))
|
|
@1)
|
|
|
|
/* Handle cases of two conversions in a row. */
|
|
(for ocvt (convert float fix_trunc)
|
|
(for icvt (convert float)
|
|
(simplify
|
|
(ocvt (icvt@1 @0))
|
|
(with
|
|
{
|
|
tree inside_type = TREE_TYPE (@0);
|
|
tree inter_type = TREE_TYPE (@1);
|
|
int inside_int = INTEGRAL_TYPE_P (inside_type);
|
|
int inside_ptr = POINTER_TYPE_P (inside_type);
|
|
int inside_float = FLOAT_TYPE_P (inside_type);
|
|
int inside_vec = TREE_CODE (inside_type) == VECTOR_TYPE;
|
|
unsigned int inside_prec = TYPE_PRECISION (inside_type);
|
|
int inside_unsignedp = TYPE_UNSIGNED (inside_type);
|
|
int inter_int = INTEGRAL_TYPE_P (inter_type);
|
|
int inter_ptr = POINTER_TYPE_P (inter_type);
|
|
int inter_float = FLOAT_TYPE_P (inter_type);
|
|
int inter_vec = TREE_CODE (inter_type) == VECTOR_TYPE;
|
|
unsigned int inter_prec = TYPE_PRECISION (inter_type);
|
|
int inter_unsignedp = TYPE_UNSIGNED (inter_type);
|
|
int final_int = INTEGRAL_TYPE_P (type);
|
|
int final_ptr = POINTER_TYPE_P (type);
|
|
int final_float = FLOAT_TYPE_P (type);
|
|
int final_vec = TREE_CODE (type) == VECTOR_TYPE;
|
|
unsigned int final_prec = TYPE_PRECISION (type);
|
|
int final_unsignedp = TYPE_UNSIGNED (type);
|
|
}
|
|
/* In addition to the cases of two conversions in a row
|
|
handled below, if we are converting something to its own
|
|
type via an object of identical or wider precision, neither
|
|
conversion is needed. */
|
|
(if (((GIMPLE && useless_type_conversion_p (type, inside_type))
|
|
|| (GENERIC
|
|
&& TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (inside_type)))
|
|
&& (((inter_int || inter_ptr) && final_int)
|
|
|| (inter_float && final_float))
|
|
&& inter_prec >= final_prec)
|
|
(ocvt @0))
|
|
|
|
/* Likewise, if the intermediate and initial types are either both
|
|
float or both integer, we don't need the middle conversion if the
|
|
former is wider than the latter and doesn't change the signedness
|
|
(for integers). Avoid this if the final type is a pointer since
|
|
then we sometimes need the middle conversion. Likewise if the
|
|
final type has a precision not equal to the size of its mode. */
|
|
(if (((inter_int && inside_int)
|
|
|| (inter_float && inside_float)
|
|
|| (inter_vec && inside_vec))
|
|
&& inter_prec >= inside_prec
|
|
&& (inter_float || inter_vec
|
|
|| inter_unsignedp == inside_unsignedp)
|
|
&& ! (final_prec != GET_MODE_PRECISION (TYPE_MODE (type))
|
|
&& TYPE_MODE (type) == TYPE_MODE (inter_type))
|
|
&& ! final_ptr
|
|
&& (! final_vec || inter_prec == inside_prec))
|
|
(ocvt @0))
|
|
|
|
/* If we have a sign-extension of a zero-extended value, we can
|
|
replace that by a single zero-extension. Likewise if the
|
|
final conversion does not change precision we can drop the
|
|
intermediate conversion. */
|
|
(if (inside_int && inter_int && final_int
|
|
&& ((inside_prec < inter_prec && inter_prec < final_prec
|
|
&& inside_unsignedp && !inter_unsignedp)
|
|
|| final_prec == inter_prec))
|
|
(ocvt @0))
|
|
|
|
/* Two conversions in a row are not needed unless:
|
|
- some conversion is floating-point (overstrict for now), or
|
|
- some conversion is a vector (overstrict for now), or
|
|
- the intermediate type is narrower than both initial and
|
|
final, or
|
|
- the intermediate type and innermost type differ in signedness,
|
|
and the outermost type is wider than the intermediate, or
|
|
- the initial type is a pointer type and the precisions of the
|
|
intermediate and final types differ, or
|
|
- the final type is a pointer type and the precisions of the
|
|
initial and intermediate types differ. */
|
|
(if (! inside_float && ! inter_float && ! final_float
|
|
&& ! inside_vec && ! inter_vec && ! final_vec
|
|
&& (inter_prec >= inside_prec || inter_prec >= final_prec)
|
|
&& ! (inside_int && inter_int
|
|
&& inter_unsignedp != inside_unsignedp
|
|
&& inter_prec < final_prec)
|
|
&& ((inter_unsignedp && inter_prec > inside_prec)
|
|
== (final_unsignedp && final_prec > inter_prec))
|
|
&& ! (inside_ptr && inter_prec != final_prec)
|
|
&& ! (final_ptr && inside_prec != inter_prec)
|
|
&& ! (final_prec != GET_MODE_PRECISION (TYPE_MODE (type))
|
|
&& TYPE_MODE (type) == TYPE_MODE (inter_type)))
|
|
(ocvt @0))))))
|