]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/match.pd
re PR sanitizer/77823 (ICE: in ubsan_encode_value, at ubsan.c:137 with -fsanitize...
[gcc.git] / gcc / match.pd
index e0ecbe2e776587a3e08cb85e222987525b7ac647..79a418fa31ef77cb88dec2e7e91431d3248551d7 100644 (file)
@@ -2,7 +2,7 @@
    This file is consumed by genmatch which produces gimple-match.c
    and generic-match.c from it.
 
-   Copyright (C) 2014-2015 Free Software Foundation, Inc.
+   Copyright (C) 2014-2016 Free Software Foundation, Inc.
    Contributed by Richard Biener <rguenther@suse.de>
    and Prathamesh Kulkarni  <bilbotheelffriend@gmail.com>
 
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3.  If not see
    zerop
    CONSTANT_CLASS_P
    tree_expr_nonnegative_p
+   integer_valued_real_p
    integer_pow2p
    HONOR_NANS)
 
@@ -46,21 +47,32 @@ along with GCC; see the file COPYING3.  If not see
 (define_operator_list simple_comparison         lt   le   eq ne ge   gt)
 (define_operator_list swapped_simple_comparison gt   ge   eq ne le   lt)
 
-(define_operator_list LOG BUILT_IN_LOGF BUILT_IN_LOG BUILT_IN_LOGL)
-(define_operator_list EXP BUILT_IN_EXPF BUILT_IN_EXP BUILT_IN_EXPL)
-(define_operator_list LOG2 BUILT_IN_LOG2F BUILT_IN_LOG2 BUILT_IN_LOG2L)
-(define_operator_list EXP2 BUILT_IN_EXP2F BUILT_IN_EXP2 BUILT_IN_EXP2L)
-(define_operator_list LOG10 BUILT_IN_LOG10F BUILT_IN_LOG10 BUILT_IN_LOG10L)
-(define_operator_list EXP10 BUILT_IN_EXP10F BUILT_IN_EXP10 BUILT_IN_EXP10L)
-(define_operator_list POW BUILT_IN_POWF BUILT_IN_POW BUILT_IN_POWL)
-(define_operator_list POW10 BUILT_IN_POW10F BUILT_IN_POW10 BUILT_IN_POW10L)
-(define_operator_list SQRT BUILT_IN_SQRTF BUILT_IN_SQRT BUILT_IN_SQRTL)
-(define_operator_list CBRT BUILT_IN_CBRTF BUILT_IN_CBRT BUILT_IN_CBRTL)
-(define_operator_list SIN BUILT_IN_SINF BUILT_IN_SIN BUILT_IN_SINL)
-(define_operator_list COS BUILT_IN_COSF BUILT_IN_COS BUILT_IN_COSL)
-(define_operator_list TAN BUILT_IN_TANF BUILT_IN_TAN BUILT_IN_TANL)
-(define_operator_list COSH BUILT_IN_COSHF BUILT_IN_COSH BUILT_IN_COSHL)
-(define_operator_list CEXPI BUILT_IN_CEXPIF BUILT_IN_CEXPI BUILT_IN_CEXPIL)
+#include "cfn-operators.pd"
+
+/* Define operand lists for math rounding functions {,i,l,ll}FN,
+   where the versions prefixed with "i" return an int, those prefixed with
+   "l" return a long and those prefixed with "ll" return a long long.
+
+   Also define operand lists:
+
+     X<FN>F for all float functions, in the order i, l, ll
+     X<FN> for all double functions, in the same order
+     X<FN>L for all long double functions, in the same order.  */
+#define DEFINE_INT_AND_FLOAT_ROUND_FN(FN) \
+  (define_operator_list X##FN##F BUILT_IN_I##FN##F \
+                                BUILT_IN_L##FN##F \
+                                BUILT_IN_LL##FN##F) \
+  (define_operator_list X##FN BUILT_IN_I##FN \
+                             BUILT_IN_L##FN \
+                             BUILT_IN_LL##FN) \
+  (define_operator_list X##FN##L BUILT_IN_I##FN##L \
+                                BUILT_IN_L##FN##L \
+                                BUILT_IN_LL##FN##L)
+
+DEFINE_INT_AND_FLOAT_ROUND_FN (FLOOR)
+DEFINE_INT_AND_FLOAT_ROUND_FN (CEIL)
+DEFINE_INT_AND_FLOAT_ROUND_FN (ROUND)
+DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 
 /* Simplifications of operations with one constant operand and
    simplifications to constants or single values.  */
@@ -135,12 +147,25 @@ along with GCC; see the file COPYING3.  If not see
     (op @0 integer_onep)
     (non_lvalue @0)))
 
-/* X / -1 is -X.  */
 (for div (trunc_div ceil_div floor_div round_div exact_div)
+  /* X / -1 is -X.  */
  (simplify
    (div @0 integer_minus_onep@1)
    (if (!TYPE_UNSIGNED (type))
-    (negate @0))))
+    (negate @0)))
+ /* X / abs (X) is X < 0 ? -1 : 1.  */ 
+ (simplify
+   (div:C @0 (abs @0))
+   (if (INTEGRAL_TYPE_P (type)
+       && TYPE_OVERFLOW_UNDEFINED (type))
+    (cond (lt @0 { build_zero_cst (type); })
+          { build_minus_one_cst (type); } { build_one_cst (type); })))
+ /* X / -X is -1.  */
+ (simplify
+   (div:C @0 (negate @0))
+   (if ((INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type))
+       && TYPE_OVERFLOW_UNDEFINED (type))
+    { build_minus_one_cst (type); })))
 
 /* For unsigned integral types, FLOOR_DIV_EXPR is the same as
    TRUNC_DIV_EXPR.  Rewrite into the latter in this case.  */
@@ -177,12 +202,26 @@ along with GCC; see the file COPYING3.  If not see
 /* Optimize -A / A to -1.0 if we don't care about
    NaNs or Infinities.  */
 (simplify
- (rdiv:c @0 (negate @0))
+ (rdiv:C @0 (negate @0))
  (if (FLOAT_TYPE_P (type)
       && ! HONOR_NANS (type)
       && ! HONOR_INFINITIES (type))
   { build_minus_one_cst (type); }))
 
+/* PR71078: x / abs(x) -> copysign (1.0, x) */
+(simplify
+ (rdiv:C (convert? @0) (convert? (abs @0)))
+  (if (SCALAR_FLOAT_TYPE_P (type)
+       && ! HONOR_NANS (type)
+       && ! HONOR_INFINITIES (type))
+   (switch
+    (if (types_match (type, float_type_node))
+     (BUILT_IN_COPYSIGNF { build_one_cst (type); } (convert @0)))
+    (if (types_match (type, double_type_node))
+     (BUILT_IN_COPYSIGN { build_one_cst (type); } (convert @0)))
+    (if (types_match (type, long_double_type_node))
+     (BUILT_IN_COPYSIGNL { build_one_cst (type); } (convert @0))))))
+
 /* In IEEE floating point, x/1 is not equivalent to x for snans.  */
 (simplify
  (rdiv @0 real_onep)
@@ -195,6 +234,28 @@ along with GCC; see the file COPYING3.  If not see
  (if (!HONOR_SNANS (type))
   (negate @0)))
 
+(if (flag_reciprocal_math)
+ /* Convert (A/B)/C to A/(B*C)  */
+ (simplify
+  (rdiv (rdiv:s @0 @1) @2)
+   (rdiv @0 (mult @1 @2)))
+
+ /* Convert A/(B/C) to (A/B)*C  */
+ (simplify
+  (rdiv @0 (rdiv:s @1 @2))
+   (mult (rdiv @0 @1) @2)))
+
+/* Optimize (X & (-A)) / A where A is a power of 2, to X >> log2(A) */
+(for div (trunc_div ceil_div floor_div round_div exact_div)
+ (simplify
+  (div (convert? (bit_and @0 INTEGER_CST@1)) INTEGER_CST@2)
+  (if (integer_pow2p (@2)
+       && tree_int_cst_sgn (@2) > 0
+       && wi::add (@2, @1) == 0
+       && tree_nop_conversion_p (type, TREE_TYPE (@0)))
+   (rshift (convert @0) { build_int_cst (integer_type_node,
+                                        wi::exact_log2 (@2)); }))))
+
 /* If ARG1 is a constant, we can convert this to a multiply by the
    reciprocal.  This does not have the same rounding properties,
    so only do this if -freciprocal-math.  We can actually
@@ -259,17 +320,23 @@ along with GCC; see the file COPYING3.  If not see
 /* X % -Y is the same as X % Y.  */
 (simplify
  (trunc_mod @0 (convert? (negate @1)))
- (if (!TYPE_UNSIGNED (type)
+ (if (INTEGRAL_TYPE_P (type)
+      && !TYPE_UNSIGNED (type)
       && !TYPE_OVERFLOW_TRAPS (type)
-      && tree_nop_conversion_p (type, TREE_TYPE (@1)))
+      && tree_nop_conversion_p (type, TREE_TYPE (@1))
+      /* Avoid this transformation if X might be INT_MIN or
+        Y might be -1, because we would then change valid
+        INT_MIN % -(-1) into invalid INT_MIN % -1.  */
+      && (expr_not_equal_to (@0, TYPE_MIN_VALUE (type))
+         || expr_not_equal_to (@1, wi::minus_one (TYPE_PRECISION
+                                                       (TREE_TYPE (@1))))))
   (trunc_mod @0 (convert @1))))
 
 /* X - (X / Y) * Y is the same as X % Y.  */
 (simplify
- (minus (convert1? @0) (convert2? (mult (trunc_div @0 @1) @1)))
- (if ((INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type))
-      && TYPE_UNSIGNED (TREE_TYPE (@0)) == TYPE_UNSIGNED (type))
-  (trunc_mod (convert @0) (convert @1))))
+ (minus (convert1? @0) (convert2? (mult:c (trunc_div @@0 @@1) @1)))
+ (if (INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type))
+  (convert (trunc_mod @0 @1))))
 
 /* Optimize TRUNC_MOD_EXPR by a power of two into a BIT_AND_EXPR,
    i.e. "X % C" into "X & (C - 1)", if X and C are positive.
@@ -322,7 +389,184 @@ along with GCC; see the file COPYING3.  If not see
    (pows (op @0) REAL_CST@1)
    (with { HOST_WIDE_INT n; }
     (if (real_isinteger (&TREE_REAL_CST (@1), &n) && (n & 1) == 0)
-     (pows @0 @1))))))
+     (pows @0 @1)))))
+ /* Likewise for powi.  */
+ (for pows (POWI)
+  (simplify
+   (pows (op @0) INTEGER_CST@1)
+   (if (wi::bit_and (@1, 1) == 0)
+    (pows @0 @1))))
+ /* Strip negate and abs from both operands of hypot.  */
+ (for hypots (HYPOT)
+  (simplify
+   (hypots (op @0) @1)
+   (hypots @0 @1))
+  (simplify
+   (hypots @0 (op @1))
+   (hypots @0 @1)))
+ /* copysign(-x, y) and copysign(abs(x), y) -> copysign(x, y).  */
+ (for copysigns (COPYSIGN)
+  (simplify
+   (copysigns (op @0) @1)
+   (copysigns @0 @1))))
+
+/* abs(x)*abs(x) -> x*x.  Should be valid for all types.  */
+(simplify
+ (mult (abs@1 @0) @1)
+ (mult @0 @0))
+
+/* cos(copysign(x, y)) -> cos(x).  Similarly for cosh.  */
+(for coss (COS COSH)
+     copysigns (COPYSIGN)
+ (simplify
+  (coss (copysigns @0 @1))
+   (coss @0)))
+
+/* pow(copysign(x, y), z) -> pow(x, z) if z is an even integer.  */
+(for pows (POW)
+     copysigns (COPYSIGN)
+ (simplify
+  (pows (copysigns @0 @2) REAL_CST@1)
+  (with { HOST_WIDE_INT n; }
+   (if (real_isinteger (&TREE_REAL_CST (@1), &n) && (n & 1) == 0)
+    (pows @0 @1)))))
+/* Likewise for powi.  */
+(for pows (POWI)
+     copysigns (COPYSIGN)
+ (simplify
+  (pows (copysigns @0 @2) INTEGER_CST@1)
+  (if (wi::bit_and (@1, 1) == 0)
+   (pows @0 @1))))
+
+(for hypots (HYPOT)
+     copysigns (COPYSIGN)
+ /* hypot(copysign(x, y), z) -> hypot(x, z).  */
+ (simplify
+  (hypots (copysigns @0 @1) @2)
+  (hypots @0 @2))
+ /* hypot(x, copysign(y, z)) -> hypot(x, y).  */
+ (simplify
+  (hypots @0 (copysigns @1 @2))
+  (hypots @0 @1)))
+
+/* copysign(x, CST) -> [-]abs (x).  */
+(for copysigns (COPYSIGN)
+ (simplify
+  (copysigns @0 REAL_CST@1)
+  (if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (@1)))
+   (negate (abs @0))
+   (abs @0))))
+
+/* copysign(copysign(x, y), z) -> copysign(x, z).  */
+(for copysigns (COPYSIGN)
+ (simplify
+  (copysigns (copysigns @0 @1) @2)
+  (copysigns @0 @2)))
+
+/* copysign(x,y)*copysign(x,y) -> x*x.  */
+(for copysigns (COPYSIGN)
+ (simplify
+  (mult (copysigns@2 @0 @1) @2)
+  (mult @0 @0)))
+
+/* ccos(-x) -> ccos(x).  Similarly for ccosh.  */
+(for ccoss (CCOS CCOSH)
+ (simplify
+  (ccoss (negate @0))
+   (ccoss @0)))
+
+/* cabs(-x) and cos(conj(x)) -> cabs(x).  */
+(for ops (conj negate)
+ (for cabss (CABS)
+  (simplify
+   (cabss (ops @0))
+   (cabss @0))))
+
+/* Fold (a * (1 << b)) into (a << b)  */
+(simplify
+ (mult:c @0 (convert? (lshift integer_onep@1 @2)))
+  (if (! FLOAT_TYPE_P (type)
+       && tree_nop_conversion_p (type, TREE_TYPE (@1)))
+   (lshift @0 @2)))
+
+/* Fold (C1/X)*C2 into (C1*C2)/X.  */
+(simplify
+ (mult (rdiv@3 REAL_CST@0 @1) REAL_CST@2)
+  (if (flag_associative_math
+       && single_use (@3))
+   (with
+    { tree tem = const_binop (MULT_EXPR, type, @0, @2); }
+    (if (tem)
+     (rdiv { tem; } @1)))))
+
+/* Convert C1/(X*C2) into (C1/C2)/X  */
+(simplify
+ (rdiv REAL_CST@0 (mult @1 REAL_CST@2))
+  (if (flag_reciprocal_math)
+   (with
+    { tree tem = const_binop (RDIV_EXPR, type, @0, @2); }
+    (if (tem)
+     (rdiv { tem; } @1)))))
+
+/* Simplify ~X & X as zero.  */
+(simplify
+ (bit_and:c (convert? @0) (convert? (bit_not @0)))
+  { build_zero_cst (type); })
+
+/* PR71636: Transform x & ((1U << b) - 1) -> x & ~(~0U << b);  */
+(simplify
+  (bit_and:c @0 (plus:s (lshift:s integer_onep @1) integer_minus_onep))
+  (if (TYPE_UNSIGNED (type))
+    (bit_and @0 (bit_not (lshift { build_all_ones_cst (type); } @1)))))
+
+/* PR35691: Transform
+   (x == 0 & y == 0) -> (x | typeof(x)(y)) == 0.
+   (x != 0 | y != 0) -> (x | typeof(x)(y)) != 0.  */
+(for bitop (bit_and bit_ior)
+     cmp (eq ne)
+ (simplify
+  (bitop (cmp @0 integer_zerop@2) (cmp @1 integer_zerop))
+   (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+       && INTEGRAL_TYPE_P (TREE_TYPE (@1))
+       && TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (TREE_TYPE (@1)))
+    (cmp (bit_ior @0 (convert @1)) @2))))
+
+/* Fold (A & ~B) - (A & B) into (A ^ B) - B.  */
+(simplify
+ (minus (bit_and:cs @0 (bit_not @1)) (bit_and:cs @0 @1))
+  (minus (bit_xor @0 @1) @1))
+(simplify
+ (minus (bit_and:s @0 INTEGER_CST@2) (bit_and:s @0 INTEGER_CST@1))
+ (if (wi::bit_not (@2) == @1)
+  (minus (bit_xor @0 @1) @1)))
+
+/* Fold (A & B) - (A & ~B) into B - (A ^ B).  */
+(simplify
+ (minus (bit_and:cs @0 @1) (bit_and:cs @0 (bit_not @1)))
+  (minus @1 (bit_xor @0 @1)))
+
+/* Simplify (X & ~Y) | (~X & Y) -> X ^ Y.  */
+(simplify
+ (bit_ior (bit_and:c @0 (bit_not @1)) (bit_and:c (bit_not @0) @1))
+  (bit_xor @0 @1))
+(simplify
+ (bit_ior:c (bit_and @0 INTEGER_CST@2) (bit_and (bit_not @0) INTEGER_CST@1))
+ (if (wi::bit_not (@2) == @1)
+  (bit_xor @0 @1)))
+
+/* PR53979: Transform ((a ^ b) | a) -> (a | b) */
+(simplify
+  (bit_ior:c (bit_xor:c @0 @1) @0)
+  (bit_ior @0 @1))
+
+/* Simplify (~X & Y) to X ^ Y if we know that (X & ~Y) is 0.  */
+#if GIMPLE
+(simplify
+ (bit_and (bit_not SSA_NAME@0) INTEGER_CST@1)
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+      && (get_nonzero_bits (@0) & wi::bit_not (@1)) == 0)
+  (bit_xor @0 @1)))
+#endif
 
 /* X % Y is smaller than Y.  */
 (for cmp (lt ge)
@@ -338,13 +582,18 @@ along with GCC; see the file COPYING3.  If not see
 
 /* x | ~0 -> ~0  */
 (simplify
-  (bit_ior @0 integer_all_onesp@1)
-  @1)
+ (bit_ior @0 integer_all_onesp@1)
+ @1)
+
+/* x | 0 -> x  */
+(simplify
+ (bit_ior @0 integer_zerop)
+ @0)
 
 /* x & 0 -> 0  */
 (simplify
 (bit_and @0 integer_zerop@1)
 @1)
+ (bit_and @0 integer_zerop@1)
+ @1)
 
 /* ~x | x -> -1 */
 /* ~x ^ x -> -1 */
@@ -375,6 +624,15 @@ along with GCC; see the file COPYING3.  If not see
   (bitop @0 @0)
   (non_lvalue @0)))
 
+/* x & C -> x if we know that x & ~C == 0.  */
+#if GIMPLE
+(simplify
+ (bit_and SSA_NAME@0 INTEGER_CST@1)
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+      && (get_nonzero_bits (@0) & wi::bit_not (@1)) == 0)
+  @0))
+#endif
+
 /* x + (x & 1) -> (x + 1) & ~1 */
 (simplify
  (plus:c @0 (bit_and:s @0 integer_onep@1))
@@ -458,8 +716,8 @@ along with GCC; see the file COPYING3.  If not see
      rop (bit_ior bit_and)
  (simplify
   (op (convert1? (bit_not @0)) (convert2? (bit_not @1)))
-  (if (tree_nop_conversion_p (type, TREE_TYPE (@0))
-       && tree_nop_conversion_p (type, TREE_TYPE (@1)))
+  (if (element_precision (type) <= element_precision (TREE_TYPE (@0))
+       && element_precision (type) <= element_precision (TREE_TYPE (@1)))
    (bit_not (rop (convert @0) (convert @1))))))
 
 /* If we are XORing or adding two BIT_AND_EXPR's, both of which are and'ing
@@ -477,15 +735,15 @@ along with GCC; see the file COPYING3.  If not see
 
 /* (X | Y) ^ X -> Y & ~ X*/
 (simplify
- (bit_xor:c (convert? (bit_ior:c @0 @1)) (convert? @0))
+ (bit_xor:c (convert1? (bit_ior:c @@0 @1)) (convert2? @0))
  (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
   (convert (bit_and @1 (bit_not @0)))))
 
 /* Convert ~X ^ ~Y to X ^ Y.  */
 (simplify
  (bit_xor (convert1? (bit_not @0)) (convert2? (bit_not @1)))
- (if (tree_nop_conversion_p (type, TREE_TYPE (@0))
-      && tree_nop_conversion_p (type, TREE_TYPE (@1)))
+ (if (element_precision (type) <= element_precision (TREE_TYPE (@0))
+      && element_precision (type) <= element_precision (TREE_TYPE (@1)))
   (bit_xor (convert @0) (convert @1))))
 
 /* Convert ~X ^ C to X ^ ~C.  */
@@ -494,10 +752,12 @@ along with GCC; see the file COPYING3.  If not see
  (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
   (bit_xor (convert @0) (bit_not @1))))
 
-/* Fold (X & Y) ^ Y as ~X & Y.  */
-(simplify
- (bit_xor:c (bit_and:c @0 @1) @1)
- (bit_and (bit_not @0) @1))
+/* Fold (X & Y) ^ Y and (X ^ Y) & Y as ~X & Y.  */
+(for opo (bit_and bit_xor)
+     opi (bit_xor bit_and)
+ (simplify
+  (opo:c (opi:c @0 @1) @1) 
+  (bit_and (bit_not @0) @1)))
 
 /* Given a bit-wise operation CODE applied to ARG0 and ARG1, see if both
    operands are another bit-wise operation with a common input.  If so,
@@ -505,13 +765,42 @@ along with GCC; see the file COPYING3.  If not see
    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))))))
 
+/* Some simple reassociation for bit operations, also handled in reassoc.  */
+/* (X & Y) & Y -> X & Y
+   (X | Y) | Y -> X | Y  */
+(for op (bit_and bit_ior)
+ (simplify
+  (op:c (convert1?@2 (op:c @0 @@1)) (convert2? @1))
+  @2))
+/* (X ^ Y) ^ Y -> X  */
+(simplify
+ (bit_xor:c (convert1? (bit_xor:c @0 @@1)) (convert2? @1))
+ (convert @0))
+/* (X & Y) & (X & Z) -> (X & Y) & Z
+   (X | Y) | (X | Z) -> (X | Y) | Z  */
+(for op (bit_and bit_ior)
+ (simplify
+  (op:c (convert1?@3 (op:c@4 @0 @1)) (convert2?@5 (op:c@6 @0 @2)))
+  (if (tree_nop_conversion_p (type, TREE_TYPE (@1))
+       && tree_nop_conversion_p (type, TREE_TYPE (@2)))
+   (if (single_use (@5) && single_use (@6))
+    (op @3 (convert @2))
+    (if (single_use (@3) && single_use (@4))
+     (op (convert @1) @5))))))
+/* (X ^ Y) ^ (X ^ Z) -> Y ^ Z  */
+(simplify
+ (bit_xor (convert1? (bit_xor:c @0 @1)) (convert2? (bit_xor:c @0 @2)))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@1))
+      && tree_nop_conversion_p (type, TREE_TYPE (@2)))
+  (bit_xor (convert @1) (convert @2))))
 
 (simplify
  (abs (abs@1 @0))
@@ -543,6 +832,13 @@ along with GCC; see the file COPYING3.  If not see
 (match negate_expr_p
  VECTOR_CST
  (if (FLOAT_TYPE_P (TREE_TYPE (type)) || TYPE_OVERFLOW_WRAPS (type))))
+
+/* (-A) * (-B) -> A * B  */
+(simplify
+ (mult:c (convert1? (negate @0)) (convert2? negate_expr_p@1))
+  (if (tree_nop_conversion_p (type, TREE_TYPE (@0))
+       && tree_nop_conversion_p (type, TREE_TYPE (@1)))
+   (mult (convert @0) (convert (negate @1)))))
  
 /* -(A + B) -> (-B) - A.  */
 (simplify
@@ -600,12 +896,6 @@ along with GCC; see the file COPYING3.  If not see
   (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)
@@ -628,6 +918,8 @@ along with GCC; see the file COPYING3.  If not see
 (match truth_valued_p
   (truth_not @0))
 
+(match (logical_inverted_value @0)
+ (truth_not @0))
 (match (logical_inverted_value @0)
  (bit_not truth_valued_p@0))
 (match (logical_inverted_value @0)
@@ -668,12 +960,16 @@ along with GCC; see the file COPYING3.  If not see
   (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)))
+   (if (TYPE_UNSIGNED (TREE_TYPE (@1)))
+    (lt @0 @1)
+    (gt @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)))
+   (if (TYPE_UNSIGNED (TREE_TYPE (@1)))
+    (le @0 @1)
+    (ge @0 @1))))
 
 /* ~~x -> x */
 (simplify
@@ -683,17 +979,20 @@ along with GCC; see the file COPYING3.  If not see
 /* Convert ~ (-A) to A - 1.  */
 (simplify
  (bit_not (convert? (negate @0)))
- (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
+ (if (element_precision (type) <= element_precision (TREE_TYPE (@0))
+      || !TYPE_UNSIGNED (TREE_TYPE (@0)))
   (convert (minus @0 { build_each_one_cst (TREE_TYPE (@0)); }))))
 
 /* Convert ~ (A - 1) or ~ (A + -1) to -A.  */
 (simplify
  (bit_not (convert? (minus @0 integer_each_onep)))
- (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
+ (if (element_precision (type) <= element_precision (TREE_TYPE (@0))
+      || !TYPE_UNSIGNED (TREE_TYPE (@0)))
   (convert (negate @0))))
 (simplify
  (bit_not (convert? (plus @0 integer_all_onesp)))
- (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
+ (if (element_precision (type) <= element_precision (TREE_TYPE (@0))
+      || !TYPE_UNSIGNED (TREE_TYPE (@0)))
   (convert (negate @0))))
 
 /* Part of convert ~(X ^ Y) to ~X ^ Y or X ^ ~Y if ~X or ~Y simplify.  */
@@ -713,7 +1012,7 @@ along with GCC; see the file COPYING3.  If not see
 
 /* Fold A - (A & B) into ~B & A.  */
 (simplify
- (minus (convert? @0) (convert?:s (bit_and:cs @0 @1)))
+ (minus (convert1? @0) (convert2?:s (bit_and:cs @@0 @1)))
  (if (tree_nop_conversion_p (type, TREE_TYPE (@0))
       && tree_nop_conversion_p (type, TREE_TYPE (@1)))
   (convert (bit_and (bit_not @1) @0))))
@@ -888,7 +1187,7 @@ along with GCC; see the file COPYING3.  If not see
      /* If the constant operation overflows we cannot do the transform
        as we would introduce undefined overflow, for example
        with (a - 1) + INT_MIN.  */
-     (with { tree cst = fold_binary (outer_op == inner_op
+     (with { tree cst = const_binop (outer_op == inner_op
                                     ? PLUS_EXPR : MINUS_EXPR, type, @1, @2); }
       (if (cst && !TREE_OVERFLOW (cst))
        (inner_op @0 { cst; } ))))))
@@ -897,7 +1196,7 @@ along with GCC; see the file COPYING3.  If not see
   (for outer_op (plus minus)
    (simplify
     (outer_op (minus CONSTANT_CLASS_P@1 @0) CONSTANT_CLASS_P@2)
-    (with { tree cst = fold_binary (outer_op, type, @1, @2); }
+    (with { tree cst = const_binop (outer_op, type, @1, @2); }
      (if (cst && !TREE_OVERFLOW (cst))
       (minus { cst; } @0)))))
 
@@ -928,7 +1227,7 @@ along with GCC; see the file COPYING3.  If not see
   /* (T)(P + A) - (T)P -> (T) A */
   (for add (plus pointer_plus)
    (simplify
-    (minus (convert (add @0 @1))
+    (minus (convert (add @@0 @1))
      (convert @0))
     (if (element_precision (type) <= element_precision (TREE_TYPE (@1))
         /* For integer types, if A has a smaller type
@@ -947,28 +1246,188 @@ along with GCC; see the file COPYING3.  If not see
         || (POINTER_TYPE_P (TREE_TYPE (@0))
             && TREE_CODE (@1) == INTEGER_CST
             && tree_int_cst_sign_bit (@1) == 0))
-     (convert @1))))))
+     (convert @1))))
 
+  /* (T)P - (T)(P + A) -> -(T) A */
+  (for add (plus pointer_plus)
+   (simplify
+    (minus (convert @0)
+     (convert (add @@0 @1)))
+    (if (element_precision (type) <= element_precision (TREE_TYPE (@1))
+        /* For integer types, if A has a smaller type
+           than T the result depends on the possible
+           overflow in P + A.
+           E.g. T=size_t, A=(unsigned)429497295, P>0.
+           However, if an overflow in P + A would cause
+           undefined behavior, we can assume that there
+           is no overflow.  */
+        || (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+            && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
+        /* For pointer types, if the conversion of A to the
+           final type requires a sign- or zero-extension,
+           then we have to punt - it is not defined which
+           one is correct.  */
+        || (POINTER_TYPE_P (TREE_TYPE (@0))
+            && TREE_CODE (@1) == INTEGER_CST
+            && tree_int_cst_sign_bit (@1) == 0))
+     (negate (convert @1)))))
 
-/* Simplifications of MIN_EXPR and MAX_EXPR.  */
+  /* (T)(P + A) - (T)(P + B) -> (T)A - (T)B */
+  (for add (plus pointer_plus)
+   (simplify
+    (minus (convert (add @@0 @1))
+     (convert (add @0 @2)))
+    (if (element_precision (type) <= element_precision (TREE_TYPE (@1))
+        /* For integer types, if A has a smaller type
+           than T the result depends on the possible
+           overflow in P + A.
+           E.g. T=size_t, A=(unsigned)429497295, P>0.
+           However, if an overflow in P + A would cause
+           undefined behavior, we can assume that there
+           is no overflow.  */
+        || (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+            && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
+        /* For pointer types, if the conversion of A to the
+           final type requires a sign- or zero-extension,
+           then we have to punt - it is not defined which
+           one is correct.  */
+        || (POINTER_TYPE_P (TREE_TYPE (@0))
+            && TREE_CODE (@1) == INTEGER_CST
+            && tree_int_cst_sign_bit (@1) == 0
+            && TREE_CODE (@2) == INTEGER_CST
+            && tree_int_cst_sign_bit (@2) == 0))
+     (minus (convert @1) (convert @2)))))))
 
-(for minmax (min max)
+
+/* Simplifications of MIN_EXPR, MAX_EXPR, fmin() and fmax().  */
+
+(for minmax (min max FMIN FMAX)
  (simplify
   (minmax @0 @0)
   @0))
+/* min(max(x,y),y) -> y.  */
+(simplify
+ (min:c (max:c @0 @1) @1)
+ @1)
+/* max(min(x,y),y) -> y.  */
+(simplify
+ (max:c (min:c @0 @1) @1)
+ @1)
+/* max(a,-a) -> abs(a).  */
+(simplify
+ (max:c @0 (negate @0))
+ (if (TREE_CODE (type) != COMPLEX_TYPE
+      && (! ANY_INTEGRAL_TYPE_P (type)
+         || TYPE_OVERFLOW_UNDEFINED (type)))
+  (abs @0)))
+/* min(a,-a) -> -abs(a).  */
+(simplify
+ (min:c @0 (negate @0))
+ (if (TREE_CODE (type) != COMPLEX_TYPE
+      && (! ANY_INTEGRAL_TYPE_P (type)
+         || TYPE_OVERFLOW_UNDEFINED (type)))
+  (negate (abs @0))))
 (simplify
  (min @0 @1)
- (if (INTEGRAL_TYPE_P (type)
-      && TYPE_MIN_VALUE (type)
-      && operand_equal_p (@1, TYPE_MIN_VALUE (type), OEP_ONLY_CONST))
-  @1))
+ (switch
+  (if (INTEGRAL_TYPE_P (type)
+       && TYPE_MIN_VALUE (type)
+       && operand_equal_p (@1, TYPE_MIN_VALUE (type), OEP_ONLY_CONST))
+   @1)
+  (if (INTEGRAL_TYPE_P (type)
+       && TYPE_MAX_VALUE (type)
+       && operand_equal_p (@1, TYPE_MAX_VALUE (type), OEP_ONLY_CONST))
+   @0)))
 (simplify
  (max @0 @1)
- (if (INTEGRAL_TYPE_P (type)
-      && TYPE_MAX_VALUE (type)
-      && operand_equal_p (@1, TYPE_MAX_VALUE (type), OEP_ONLY_CONST))
-  @1))
+ (switch
+  (if (INTEGRAL_TYPE_P (type)
+       && TYPE_MAX_VALUE (type)
+       && operand_equal_p (@1, TYPE_MAX_VALUE (type), OEP_ONLY_CONST))
+   @1)
+  (if (INTEGRAL_TYPE_P (type)
+       && TYPE_MIN_VALUE (type)
+       && operand_equal_p (@1, TYPE_MIN_VALUE (type), OEP_ONLY_CONST))
+   @0)))
+
+/* (convert (minmax ((convert (x) c)))) -> minmax (x c) if x is promoted
+   and the outer convert demotes the expression back to x's type.  */
+(for minmax (min max)
+ (simplify
+  (convert (minmax@0 (convert @1) INTEGER_CST@2))
+  (if (types_match (@1, type) && int_fits_type_p (@2, type)
+       && TYPE_SIGN (TREE_TYPE (@0)) == TYPE_SIGN (type)
+       && TYPE_PRECISION (TREE_TYPE (@0)) > TYPE_PRECISION (type))
+   (minmax @1 (convert @2)))))
+
+(for minmax (FMIN FMAX)
+ /* If either argument is NaN, return the other one.  Avoid the
+    transformation if we get (and honor) a signalling NaN.  */
+ (simplify
+  (minmax:c @0 REAL_CST@1)
+  (if (real_isnan (TREE_REAL_CST_PTR (@1))
+       && (!HONOR_SNANS (@1) || !TREE_REAL_CST (@1).signalling))
+   @0)))
+/* Convert fmin/fmax to MIN_EXPR/MAX_EXPR.  C99 requires these
+   functions to return the numeric arg if the other one is NaN.
+   MIN and MAX don't honor that, so only transform if -ffinite-math-only
+   is set.  C99 doesn't require -0.0 to be handled, so we don't have to
+   worry about it either.  */
+(if (flag_finite_math_only)
+ (simplify
+  (FMIN @0 @1)
+  (min @0 @1))
+ (simplify
+  (FMAX @0 @1)
+  (max @0 @1)))
+/* min (-A, -B) -> -max (A, B)  */
+(for minmax (min max FMIN FMAX)
+     maxmin (max min FMAX FMIN)
+ (simplify
+  (minmax (negate:s@2 @0) (negate:s@3 @1))
+  (if (FLOAT_TYPE_P (TREE_TYPE (@0))
+       || (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+           && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))))
+   (negate (maxmin @0 @1)))))
+/* MIN (~X, ~Y) -> ~MAX (X, Y)
+   MAX (~X, ~Y) -> ~MIN (X, Y)  */
+(for minmax (min max)
+ maxmin (max min)
+ (simplify
+  (minmax (bit_not:s@2 @0) (bit_not:s@3 @1))
+  (bit_not (maxmin @0 @1))))
 
+/* MIN (X, Y) == X -> X <= Y  */
+(for minmax (min min max max)
+     cmp    (eq  ne  eq  ne )
+     out    (le  gt  ge  lt )
+ (simplify
+  (cmp:c (minmax:c @0 @1) @0)
+  (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0)))
+   (out @0 @1))))
+/* MIN (X, 5) == 0 -> X == 0
+   MIN (X, 5) == 7 -> false  */
+(for cmp (eq ne)
+ (simplify
+  (cmp (min @0 INTEGER_CST@1) INTEGER_CST@2)
+  (if (wi::lt_p (@1, @2, TYPE_SIGN (TREE_TYPE (@0))))
+   { constant_boolean_node (cmp == NE_EXPR, type); }
+   (if (wi::gt_p (@1, @2, TYPE_SIGN (TREE_TYPE (@0))))
+    (cmp @0 @2)))))
+(for cmp (eq ne)
+ (simplify
+  (cmp (max @0 INTEGER_CST@1) INTEGER_CST@2)
+  (if (wi::gt_p (@1, @2, TYPE_SIGN (TREE_TYPE (@0))))
+   { constant_boolean_node (cmp == NE_EXPR, type); }
+   (if (wi::lt_p (@1, @2, TYPE_SIGN (TREE_TYPE (@0))))
+    (cmp @0 @2)))))
+/* MIN (X, C1) < C2 -> X < C2 || C1 < C2  */
+(for minmax (min     min     max     max     min     min     max     max    )
+     cmp    (lt      le      gt      ge      gt      ge      lt      le     )
+     comb   (bit_ior bit_ior bit_ior bit_ior bit_and bit_and bit_and bit_and)
+ (simplify
+  (cmp (minmax @0 INTEGER_CST@1) INTEGER_CST@2)
+  (comb (cmp @0 @2) (cmp @1 @2))))
 
 /* Simplifications of shift and rotates.  */
 
@@ -1018,7 +1477,7 @@ along with GCC; see the file COPYING3.  If not see
    RROTATE_EXPR by a new constant.  */
 (simplify
  (lrotate @0 INTEGER_CST@1)
- (rrotate @0 { fold_binary (MINUS_EXPR, TREE_TYPE (@1),
+ (rrotate @0 { const_binop (MINUS_EXPR, TREE_TYPE (@1),
                            build_int_cst (TREE_TYPE (@1),
                                           element_precision (type)), @1); }))
 
@@ -1087,7 +1546,7 @@ along with GCC; see the file COPYING3.  If not see
        unsigned int prec;
 
        if (shift == LSHIFT_EXPR)
-        zerobits = ((((unsigned HOST_WIDE_INT) 1) << shiftc) - 1);
+        zerobits = ((HOST_WIDE_INT_1U << shiftc) - 1);
        else if (shift == RSHIFT_EXPR
                && (TYPE_PRECISION (shift_type)
                    == GET_MODE_PRECISION (TYPE_MODE (shift_type))))
@@ -1113,7 +1572,7 @@ along with GCC; see the file COPYING3.  If not see
                      is all ones.  */
                 }
             }
-          zerobits = ~(unsigned HOST_WIDE_INT) 0;
+          zerobits = HOST_WIDE_INT_M1U;
           if (shiftc < prec)
             {
               zerobits >>= HOST_BITS_PER_WIDE_INT - shiftc;
@@ -1144,11 +1603,11 @@ along with GCC; see the file COPYING3.  If not see
              mode's mask.  */
           for (prec = BITS_PER_UNIT;
                prec < HOST_BITS_PER_WIDE_INT; prec <<= 1)
-            if (newmask == (((unsigned HOST_WIDE_INT) 1) << prec) - 1)
+            if (newmask == (HOST_WIDE_INT_1U << prec) - 1)
               break;
         }
         (if (prec < HOST_BITS_PER_WIDE_INT
-             || newmask == ~(unsigned HOST_WIDE_INT) 0)
+             || newmask == HOST_WIDE_INT_M1U)
          (with
           { tree newmaskt = build_int_cst_type (TREE_TYPE (@2), newmask); }
           (if (!tree_int_cst_equal (newmaskt, @2))
@@ -1166,6 +1625,30 @@ along with GCC; see the file COPYING3.  If not see
     (with { tree mask = int_const_binop (shift, fold_convert (type, @2), @1); }
      (bit_op (shift (convert @0) @1) { mask; }))))))
 
+/* ~(~X >> Y) -> X >> Y (for arithmetic shift).  */
+(simplify
+ (bit_not (convert1?:s (rshift:s (convert2?@0 (bit_not @1)) @2)))
+  (if (!TYPE_UNSIGNED (TREE_TYPE (@0))
+       && (element_precision (TREE_TYPE (@0))
+          <= element_precision (TREE_TYPE (@1))
+          || !TYPE_UNSIGNED (TREE_TYPE (@1))))
+   (with
+    { tree shift_type = TREE_TYPE (@0); }
+     (convert (rshift (convert:shift_type @1) @2)))))
+
+/* ~(~X >>r Y) -> X >>r Y
+   ~(~X <<r Y) -> X <<r Y */
+(for rotate (lrotate rrotate)
+ (simplify
+  (bit_not (convert1?:s (rotate:s (convert2?@0 (bit_not @1)) @2)))
+   (if ((element_precision (TREE_TYPE (@0))
+        <= element_precision (TREE_TYPE (@1))
+        || !TYPE_UNSIGNED (TREE_TYPE (@1)))
+        && (element_precision (type) <= element_precision (TREE_TYPE (@0))
+           || !TYPE_UNSIGNED (TREE_TYPE (@0))))
+    (with
+     { tree rotate_type = TREE_TYPE (@0); }
+      (convert (rotate (convert:rotate_type @1) @2))))))
 
 /* Simplifications of conversions.  */
 
@@ -1254,14 +1737,11 @@ along with GCC; see the file COPYING3.  If not see
        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.  */
+       then we sometimes need the middle conversion.  */
     (if (((inter_int && inside_int) || (inter_float && inside_float))
         && (final_int || final_float)
         && inter_prec >= inside_prec
-        && (inter_float || inter_unsignedp == inside_unsignedp)
-        && ! (final_prec != GET_MODE_PRECISION (TYPE_MODE (type))
-              && TYPE_MODE (type) == TYPE_MODE (inter_type)))
+        && (inter_float || inter_unsignedp == inside_unsignedp))
      (ocvt @0))
 
     /* If we have a sign-extension of a zero-extended value, we can
@@ -1294,14 +1774,13 @@ along with GCC; see the file COPYING3.  If not see
         && ((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)))
+        && ! (final_ptr && inside_prec != inter_prec))
      (ocvt @0))
 
     /* A truncation to an unsigned type (a zero-extension) should be
        canonicalized as bitwise and of a mask.  */
-    (if (final_int && inter_int && inside_int
+    (if (GIMPLE /* PR70366: doing this in GENERIC breaks -Wconversion.  */
+        && final_int && inter_int && inside_int
         && final_prec == inside_prec
         && final_prec > inter_prec
         && inter_unsignedp)
@@ -1334,8 +1813,7 @@ along with GCC; see the file COPYING3.  If not see
 
 /* (X /[ex] A) * A -> X.  */
 (simplify
-  (mult (convert? (exact_div @0 @1)) @1)
-  /* Look through a sign-changing conversion.  */
+  (mult (convert1? (exact_div @0 @@1)) (convert2? @1))
   (convert @0))
 
 /* Canonicalization of binary operations.  */
@@ -1344,15 +1822,17 @@ along with GCC; see the file COPYING3.  If not see
 (simplify
  (plus @0 REAL_CST@1)
  (if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (@1)))
-  (with { tree tem = fold_unary (NEGATE_EXPR, type, @1); }
+  (with { tree tem = const_unop (NEGATE_EXPR, type, @1); }
    (if (!TREE_OVERFLOW (tem) || !flag_trapping_math)
     (minus @0 { tem; })))))
 
-/* Convert x+x into x*2.0.  */
+/* Convert x+x into x*2.  */
 (simplify
  (plus @0 @0)
  (if (SCALAR_FLOAT_TYPE_P (type))
-  (mult @0 { build_real (type, dconst2); })))
+  (mult @0 { build_real (type, dconst2); })
+  (if (INTEGRAL_TYPE_P (type))
+   (mult @0 { build_int_cst (type, 2); }))))
 
 (simplify
  (minus integer_zerop @1)
@@ -1371,6 +1851,11 @@ along with GCC; see the file COPYING3.  If not see
  (mult @0 integer_minus_onep)
  (negate @0))
 
+/* True if we can easily extract the real and imaginary parts of a complex
+   number.  */
+(match compositional_complex
+ (convert? (complex @0 @1)))
+
 /* COMPLEX_EXPR and REALPART/IMAGPART_EXPR cancellations.  */
 (simplify
  (complex (realpart @0) (imagpart @0))
@@ -1460,6 +1945,29 @@ along with GCC; see the file COPYING3.  If not see
  (simplify
   (cnd @0 @1 (cnd @0 @2 @3))
   (cnd @0 @1 @3))
+ /* A ? B : (!A ? C : X) -> A ? B : C.  */
+ /* ???  This matches embedded conditions open-coded because genmatch
+    would generate matching code for conditions in separate stmts only.
+    The following is still important to merge then and else arm cases
+    from if-conversion.  */
+ (simplify
+  (cnd @0 @1 (cnd @2 @3 @4))
+  (if (COMPARISON_CLASS_P (@0)
+       && COMPARISON_CLASS_P (@2)
+       && invert_tree_comparison
+           (TREE_CODE (@0), HONOR_NANS (TREE_OPERAND (@0, 0))) == TREE_CODE (@2)
+       && operand_equal_p (TREE_OPERAND (@0, 0), TREE_OPERAND (@2, 0), 0)
+       && operand_equal_p (TREE_OPERAND (@0, 1), TREE_OPERAND (@2, 1), 0))
+   (cnd @0 @1 @3)))
+ (simplify
+  (cnd @0 (cnd @1 @2 @3) @4)
+  (if (COMPARISON_CLASS_P (@0)
+       && COMPARISON_CLASS_P (@1)
+       && invert_tree_comparison
+           (TREE_CODE (@0), HONOR_NANS (TREE_OPERAND (@0, 0))) == TREE_CODE (@1)
+       && operand_equal_p (TREE_OPERAND (@0, 0), TREE_OPERAND (@1, 0), 0)
+       && operand_equal_p (TREE_OPERAND (@0, 1), TREE_OPERAND (@1, 1), 0))
+   (cnd @0 @3 @4)))
 
  /* A ? B : B -> B.  */
  (simplify
@@ -1471,26 +1979,26 @@ along with GCC; see the file COPYING3.  If not see
   (cnd (logical_inverted_value truth_valued_p@0) @1 @2)
   (cnd @0 @2 @1)))
 
-/* A + (B vcmp C ? 1 : 0) -> A - (B vcmp C), since vector comparisons
-   return all-1 or all-0 results.  */
+/* A + (B vcmp C ? 1 : 0) -> A - (B vcmp C ? -1 : 0), since vector comparisons
+   return all -1 or all 0 results.  */
 /* ??? We could instead convert all instances of the vec_cond to negate,
    but that isn't necessarily a win on its own.  */
 (simplify
- (plus:c @3 (view_convert? (vec_cond @0 integer_each_onep@1 integer_zerop@2)))
+ (plus:c @3 (view_convert? (vec_cond:s @0 integer_each_onep@1 integer_zerop@2)))
  (if (VECTOR_TYPE_P (type)
-      && TYPE_VECTOR_SUBPARTS (type) == TYPE_VECTOR_SUBPARTS (TREE_TYPE (@0))
+      && TYPE_VECTOR_SUBPARTS (type) == TYPE_VECTOR_SUBPARTS (TREE_TYPE (@1))
       && (TYPE_MODE (TREE_TYPE (type))
-          == TYPE_MODE (TREE_TYPE (TREE_TYPE (@0)))))
-  (minus @3 (view_convert @0))))
+          == TYPE_MODE (TREE_TYPE (TREE_TYPE (@1)))))
+  (minus @3 (view_convert (vec_cond @0 (negate @1) @2)))))
 
-/* ... likewise A - (B vcmp C ? 1 : 0) -> A + (B vcmp C).  */
+/* ... likewise A - (B vcmp C ? 1 : 0) -> A + (B vcmp C ? -1 : 0).  */
 (simplify
- (minus @3 (view_convert? (vec_cond @0 integer_each_onep@1 integer_zerop@2)))
+ (minus @3 (view_convert? (vec_cond:s @0 integer_each_onep@1 integer_zerop@2)))
  (if (VECTOR_TYPE_P (type)
-      && TYPE_VECTOR_SUBPARTS (type) == TYPE_VECTOR_SUBPARTS (TREE_TYPE (@0))
+      && TYPE_VECTOR_SUBPARTS (type) == TYPE_VECTOR_SUBPARTS (TREE_TYPE (@1))
       && (TYPE_MODE (TREE_TYPE (type))
-          == TYPE_MODE (TREE_TYPE (TREE_TYPE (@0)))))
-  (plus @3 (view_convert @0))))
+          == TYPE_MODE (TREE_TYPE (TREE_TYPE (@1)))))
+  (plus @3 (view_convert (vec_cond @0 (negate @1) @2)))))
 
 
 /* Simplifications of comparisons.  */
@@ -1565,12 +2073,13 @@ along with GCC; see the file COPYING3.  If not see
 (for cmp (simple_comparison)
      scmp (swapped_simple_comparison)
  (simplify
-  (cmp (mult @0 INTEGER_CST@1) integer_zerop@2)
+  (cmp (mult@3 @0 INTEGER_CST@1) integer_zerop@2)
   /* Handle unfolded multiplication by zero.  */
   (if (integer_zerop (@1))
    (cmp @1 @2)
    (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
-       && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
+       && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))
+       && single_use (@3))
     /* If @1 is negative we swap the sense of the comparison.  */
     (if (tree_int_cst_sgn (@1) < 0)
      (scmp @0 @2)
@@ -1578,26 +2087,29 @@ along with GCC; see the file COPYING3.  If not see
  
 /* Simplify comparison of something with itself.  For IEEE
    floating-point, we can only do some of these simplifications.  */
-(simplify
- (eq @0 @0)
- (if (! FLOAT_TYPE_P (TREE_TYPE (@0))
-      || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (@0))))
-  { constant_boolean_node (true, type); }))
-(for cmp (ge le)
+(for cmp (eq ge le)
  (simplify
   (cmp @0 @0)
-  (eq @0 @0)))
+  (if (! FLOAT_TYPE_P (TREE_TYPE (@0))
+       || ! HONOR_NANS (@0))
+   { constant_boolean_node (true, type); }
+   (if (cmp != EQ_EXPR)
+    (eq @0 @0)))))
 (for cmp (ne gt lt)
  (simplify
   (cmp @0 @0)
   (if (cmp != NE_EXPR
        || ! FLOAT_TYPE_P (TREE_TYPE (@0))
-       || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (@0))))
+       || ! HONOR_NANS (@0))
    { constant_boolean_node (false, type); })))
 (for cmp (unle unge uneq)
  (simplify
   (cmp @0 @0)
   { constant_boolean_node (true, type); }))
+(for cmp (unlt ungt)
+ (simplify
+  (cmp @0 @0)
+  (unordered @0 @0)))
 (simplify
  (ltgt @0 @0)
  (if (!flag_trapping_math)
@@ -1606,15 +2118,17 @@ along with GCC; see the file COPYING3.  If not see
 /* Fold ~X op ~Y as Y op X.  */
 (for cmp (simple_comparison)
  (simplify
-  (cmp (bit_not @0) (bit_not @1))
-  (cmp @1 @0)))
+  (cmp (bit_not@2 @0) (bit_not@3 @1))
+  (if (single_use (@2) && single_use (@3))
+   (cmp @1 @0))))
 
 /* Fold ~X op C as X op' ~C, where op' is the swapped comparison.  */
 (for cmp (simple_comparison)
      scmp (swapped_simple_comparison)
  (simplify
-  (cmp (bit_not @0) CONSTANT_CLASS_P@1)
-  (if (TREE_CODE (@1) == INTEGER_CST || TREE_CODE (@1) == VECTOR_CST)
+  (cmp (bit_not@2 @0) CONSTANT_CLASS_P@1)
+  (if (single_use (@2)
+       && (TREE_CODE (@1) == INTEGER_CST || TREE_CODE (@1) == VECTOR_CST))
    (scmp @0 (bit_not @1)))))
 
 (for cmp (simple_comparison)
@@ -1749,6 +2263,25 @@ along with GCC; see the file COPYING3.  If not see
        { constant_boolean_node (true, type); })
        /* sqrt(x) > y is the same as x >= 0, if y is negative.  */
        (ge @0 { build_real (TREE_TYPE (@0), dconst0); })))
+     (if (real_equal (TREE_REAL_CST_PTR (@1), &dconst0))
+      (switch
+       /* sqrt(x) < 0 is always false.  */
+       (if (cmp == LT_EXPR)
+       { constant_boolean_node (false, type); })
+       /* sqrt(x) >= 0 is always true if we don't care about NaNs.  */
+       (if (cmp == GE_EXPR && !HONOR_NANS (@0))
+       { constant_boolean_node (true, type); })
+       /* sqrt(x) <= 0 -> x == 0.  */
+       (if (cmp == LE_EXPR)
+       (eq @0 @1))
+       /* Otherwise sqrt(x) cmp 0 -> x cmp 0.  Here cmp can be >=, >,
+          == or !=.  In the last case:
+
+           (sqrt(x) != 0) == (NaN != 0) == true == (x != 0)
+
+         if x is negative or NaN.  Due to -funsafe-math-optimizations,
+         the results for other x follow from natural arithmetic.  */
+       (cmp @0 @1)))
      (if (cmp == GT_EXPR || cmp == GE_EXPR)
       (with
        {
@@ -1816,6 +2349,24 @@ along with GCC; see the file COPYING3.  If not see
  (bit_and:c (ordered @0 @0) (ordered:c@2 @0 @1))
  @2)
 
+/* Simple range test simplifications.  */
+/* A < B || A >= B -> true.  */
+(for test1 (lt le le le ne ge)
+     test2 (ge gt ge ne eq ne)
+ (simplify
+  (bit_ior:c (test1 @0 @1) (test2 @0 @1))
+  (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+       || VECTOR_INTEGER_TYPE_P (TREE_TYPE (@0)))
+   { constant_boolean_node (true, type); })))
+/* A < B && A >= B -> false.  */
+(for test1 (lt lt lt le ne eq)
+     test2 (ge gt eq gt eq gt)
+ (simplify
+  (bit_and:c (test1 @0 @1) (test2 @0 @1))
+  (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+       || VECTOR_INTEGER_TYPE_P (TREE_TYPE (@0)))
+   { constant_boolean_node (false, type); })))
+
 /* -A CMP -B -> B CMP A.  */
 (for cmp (tcc_comparison)
      scmp (swapped_tcc_comparison)
@@ -1830,7 +2381,7 @@ along with GCC; see the file COPYING3.  If not see
   (if (FLOAT_TYPE_P (TREE_TYPE (@0))
        || (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
           && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))))
-   (with { tree tem = fold_unary (NEGATE_EXPR, TREE_TYPE (@0), @1); }
+   (with { tree tem = const_unop (NEGATE_EXPR, TREE_TYPE (@0), @1); }
     (if (tem && !TREE_OVERFLOW (tem))
      (scmp @0 { tem; }))))))
 
@@ -1844,7 +2395,7 @@ along with GCC; see the file COPYING3.  If not see
 (for cmp (simple_comparison)
  (simplify
   (cmp (convert@0 @00) (convert?@1 @10))
-  (if (TREE_CODE (TREE_TYPE (@0)) == INTEGER_TYPE
+  (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
        /* Disable this optimization if we're casting a function pointer
          type on targets that require function pointer canonicalization.  */
        && !(targetm.have_canonicalize_funcptr_for_compare ()
@@ -1869,19 +2420,20 @@ along with GCC; see the file COPYING3.  If not see
     (if (TYPE_PRECISION (TREE_TYPE (@0)) > TYPE_PRECISION (TREE_TYPE (@00)))
      /* If possible, express the comparison in the shorter mode.  */
      (if ((cmp == EQ_EXPR || cmp == NE_EXPR
-          || TYPE_UNSIGNED (TREE_TYPE (@0)) == TYPE_UNSIGNED (TREE_TYPE (@00)))
+          || TYPE_UNSIGNED (TREE_TYPE (@0)) == TYPE_UNSIGNED (TREE_TYPE (@00))
+          || (!TYPE_UNSIGNED (TREE_TYPE (@0))
+              && TYPE_UNSIGNED (TREE_TYPE (@00))))
          && (types_match (TREE_TYPE (@10), TREE_TYPE (@00))
              || ((TYPE_PRECISION (TREE_TYPE (@00))
                   >= TYPE_PRECISION (TREE_TYPE (@10)))
                  && (TYPE_UNSIGNED (TREE_TYPE (@00))
                      == TYPE_UNSIGNED (TREE_TYPE (@10))))
              || (TREE_CODE (@10) == INTEGER_CST
-                 && (TREE_CODE (TREE_TYPE (@00)) == INTEGER_TYPE
-                     || TREE_CODE (TREE_TYPE (@00)) == BOOLEAN_TYPE)
+                 && INTEGRAL_TYPE_P (TREE_TYPE (@00))
                  && int_fits_type_p (@10, TREE_TYPE (@00)))))
       (cmp @00 (convert @10))
       (if (TREE_CODE (@10) == INTEGER_CST
-          && TREE_CODE (TREE_TYPE (@00)) == INTEGER_TYPE
+          && INTEGRAL_TYPE_P (TREE_TYPE (@00))
           && !int_fits_type_p (@10, TREE_TYPE (@00)))
        (with
        {
@@ -1995,8 +2547,15 @@ along with GCC; see the file COPYING3.  If not see
     (with
      {
        int equal = 2;
-       if (decl_in_symtab_p (base0)
-          && decl_in_symtab_p (base1))
+       /* Punt in GENERIC on variables with value expressions;
+         the value expressions might point to fields/elements
+         of other vars etc.  */
+       if (GENERIC
+          && ((VAR_P (base0) && DECL_HAS_VALUE_EXPR_P (base0))
+              || (VAR_P (base1) && DECL_HAS_VALUE_EXPR_P (base1))))
+        ;
+       else if (decl_in_symtab_p (base0)
+               && decl_in_symtab_p (base1))
          equal = symtab_node::get_create (base0)
                   ->equal_address_to (symtab_node::get_create (base1));
        else if ((DECL_P (base0)
@@ -2039,6 +2598,29 @@ along with GCC; see the file COPYING3.  If not see
        (if (cmp == NE_EXPR)
         { constant_boolean_node (true, type); })))))))))
 
+/* Simplify pointer equality compares using PTA.  */
+(for neeq (ne eq)
+ (simplify
+  (neeq @0 @1)
+  (if (POINTER_TYPE_P (TREE_TYPE (@0))
+       && ptrs_compare_unequal (@0, @1))
+   { neeq == EQ_EXPR ? boolean_false_node : boolean_true_node; })))
+
+/* PR70920: Transform (intptr_t)x eq/ne CST to x eq/ne (typeof x) CST.
+   and (typeof ptr_cst) x eq/ne ptr_cst to x eq/ne (typeof x) CST.
+   Disable the transform if either operand is pointer to function.
+   This broke pr22051-2.c for arm where function pointer
+   canonicalizaion is not wanted.  */
+
+(for cmp (ne eq)
+ (simplify
+  (cmp (convert @0) INTEGER_CST@1)
+  (if ((POINTER_TYPE_P (TREE_TYPE (@0)) && !FUNC_OR_METHOD_TYPE_P (TREE_TYPE (TREE_TYPE (@0)))
+       && INTEGRAL_TYPE_P (TREE_TYPE (@1)))
+      || (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && POINTER_TYPE_P (TREE_TYPE (@1))
+         && !FUNC_OR_METHOD_TYPE_P (TREE_TYPE (TREE_TYPE (@1)))))
+   (cmp @0 (convert @1)))))
+
 /* Non-equality compare simplifications from fold_binary  */
 (for cmp (lt gt le ge)
  /* Comparisons with the highest or lowest possible integer of
@@ -2134,6 +2716,60 @@ along with GCC; see the file COPYING3.  If not see
    replace if (x == 0) with tem = ~x; if (tem != 0) which is
    clearly less optimal and which we'll transform again in forwprop.  */
 
+/* When one argument is a constant, overflow detection can be simplified.
+   Currently restricted to single use so as not to interfere too much with
+   ADD_OVERFLOW detection in tree-ssa-math-opts.c.
+   A + CST CMP A  ->  A CMP' CST' */
+(for cmp (lt le ge gt)
+     out (gt gt le le)
+ (simplify
+  (cmp:c (plus@2 @0 INTEGER_CST@1) @0)
+  (if (TYPE_UNSIGNED (TREE_TYPE (@0))
+       && TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))
+       && wi::ne_p (@1, 0)
+       && single_use (@2))
+   (out @0 { wide_int_to_tree (TREE_TYPE (@0), wi::max_value
+              (TYPE_PRECISION (TREE_TYPE (@0)), UNSIGNED) - @1); }))))
+
+/* To detect overflow in unsigned A - B, A < B is simpler than A - B > A.
+   However, the detection logic for SUB_OVERFLOW in tree-ssa-math-opts.c
+   expects the long form, so we restrict the transformation for now.  */
+(for cmp (gt le)
+ (simplify
+  (cmp:c (minus@2 @0 @1) @0)
+  (if (single_use (@2)
+       && ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+       && TYPE_UNSIGNED (TREE_TYPE (@0))
+       && TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
+   (cmp @1 @0))))
+
+/* Testing for overflow is unnecessary if we already know the result.  */
+/* A - B > A  */
+(for cmp (gt le)
+     out (ne eq)
+ (simplify
+  (cmp:c (realpart (IFN_SUB_OVERFLOW@2 @0 @1)) @0)
+  (if (TYPE_UNSIGNED (TREE_TYPE (@0))
+       && types_match (TREE_TYPE (@0), TREE_TYPE (@1)))
+   (out (imagpart @2) { build_zero_cst (TREE_TYPE (@0)); }))))
+/* A + B < A  */
+(for cmp (lt ge)
+     out (ne eq)
+ (simplify
+  (cmp:c (realpart (IFN_ADD_OVERFLOW:c@2 @0 @1)) @0)
+  (if (TYPE_UNSIGNED (TREE_TYPE (@0))
+       && types_match (TREE_TYPE (@0), TREE_TYPE (@1)))
+   (out (imagpart @2) { build_zero_cst (TREE_TYPE (@0)); }))))
+
+/* For unsigned operands, -1 / B < A checks whether A * B would overflow.
+   Simplify it to __builtin_mul_overflow (A, B, <unused>).  */
+(for cmp (lt ge)
+     out (ne eq)
+ (simplify
+  (cmp:c (trunc_div:s integer_all_onesp @1) @0)
+  (if (TYPE_UNSIGNED (TREE_TYPE (@0)) && !VECTOR_TYPE_P (TREE_TYPE (@0)))
+   (with { tree t = TREE_TYPE (@0), cpx = build_complex_type (t); }
+    (out (imagpart (IFN_MUL_OVERFLOW:cpx @0 @1)) { build_zero_cst (t); })))))
 
 /* Simplification of math builtins.  These rules must all be optimizations
    as well as IL simplifications.  If there is a possibility that the new
@@ -2184,12 +2820,16 @@ along with GCC; see the file COPYING3.  If not see
    (rdiv @0 (exps:s @1))
     (mult @0 (exps (negate @1)))))
 
- /* Special case, optimize logN(expN(x)) = x.  */
  (for logs (LOG LOG2 LOG10 LOG10)
       exps (EXP EXP2 EXP10 POW10)
+  /* logN(expN(x)) -> x.  */
   (simplify
    (logs (exps @0))
-    @0))
+   @0)
+  /* expN(logN(x)) -> x.  */
+  (simplify
+   (exps (logs @0))
+   @0))
 
  /* Optimize logN(func()) for various exponential functions.  We
     want to determine the value "x" and the power "exponent" in
@@ -2198,32 +2838,33 @@ along with GCC; see the file COPYING3.  If not see
       exps (EXP2 EXP10 POW10 EXP  EXP10 POW10 EXP   EXP2)
   (simplify
    (logs (exps @0))
-   (with {
-     tree x;
-     switch (exps)
-       {
-       CASE_FLT_FN (BUILT_IN_EXP):
-         /* Prepare to do logN(exp(exponent)) -> exponent*logN(e).  */
-        x = build_real_truncate (type, dconst_e ());
-         break;
-       CASE_FLT_FN (BUILT_IN_EXP2):
-         /* Prepare to do logN(exp2(exponent)) -> exponent*logN(2).  */
-         x = build_real (type, dconst2);
-         break;
-       CASE_FLT_FN (BUILT_IN_EXP10):
-       CASE_FLT_FN (BUILT_IN_POW10):
-        /* Prepare to do logN(exp10(exponent)) -> exponent*logN(10).  */
-        {
-          REAL_VALUE_TYPE dconst10;
-          real_from_integer (&dconst10, VOIDmode, 10, SIGNED);
-          x = build_real (type, dconst10);
-        }
-         break;
-       default:
-        gcc_unreachable ();
-       }
-     }
-    (mult (logs { x; }) @0))))
+   (if (SCALAR_FLOAT_TYPE_P (type))
+    (with {
+      tree x;
+      switch (exps)
+       {
+       CASE_CFN_EXP:
+         /* Prepare to do logN(exp(exponent)) -> exponent*logN(e).  */
+         x = build_real_truncate (type, dconst_e ());
+         break;
+       CASE_CFN_EXP2:
+         /* Prepare to do logN(exp2(exponent)) -> exponent*logN(2).  */
+         x = build_real (type, dconst2);
+         break;
+       CASE_CFN_EXP10:
+       CASE_CFN_POW10:
+         /* Prepare to do logN(exp10(exponent)) -> exponent*logN(10).  */
+         {
+           REAL_VALUE_TYPE dconst10;
+           real_from_integer (&dconst10, VOIDmode, 10, SIGNED);
+           x = build_real (type, dconst10);
+         }
+         break;
+       default:
+         gcc_unreachable ();
+       }
+      }
+     (mult (logs { x; }) @0)))))
 
  (for logs (LOG LOG
             LOG2 LOG2
@@ -2231,23 +2872,24 @@ along with GCC; see the file COPYING3.  If not see
       exps (SQRT CBRT)
   (simplify
    (logs (exps @0))
-   (with {
-     tree x;
-     switch (exps)
-       {
-       CASE_FLT_FN (BUILT_IN_SQRT):
-        /* Prepare to do logN(sqrt(x)) -> 0.5*logN(x).  */
-        x = build_real (type, dconsthalf);
-         break;
-       CASE_FLT_FN (BUILT_IN_CBRT):
-        /* Prepare to do logN(cbrt(x)) -> (1/3)*logN(x).  */
-         x = build_real_truncate (type, dconst_third ());
-         break;
-       default:
-        gcc_unreachable ();
-       }
-     }
-    (mult { x; } (logs @0)))))
+   (if (SCALAR_FLOAT_TYPE_P (type))
+    (with {
+      tree x;
+      switch (exps)
+       {
+       CASE_CFN_SQRT:
+         /* Prepare to do logN(sqrt(x)) -> 0.5*logN(x).  */
+         x = build_real (type, dconsthalf);
+         break;
+       CASE_CFN_CBRT:
+         /* Prepare to do logN(cbrt(x)) -> (1/3)*logN(x).  */
+         x = build_real_truncate (type, dconst_third ());
+         break;
+       default:
+         gcc_unreachable ();
+       }
+      }
+     (mult { x; } (logs @0))))))
 
  /* logN(pow(x,exponent)) -> exponent*logN(x).  */
  (for logs (LOG LOG2 LOG10)
@@ -2258,6 +2900,7 @@ along with GCC; see the file COPYING3.  If not see
 
  (for sqrts (SQRT)
       cbrts (CBRT)
+      pows (POW)
       exps (EXP EXP2 EXP10 POW10)
   /* sqrt(expN(x)) -> expN(x*0.5).  */
   (simplify
@@ -2266,7 +2909,69 @@ along with GCC; see the file COPYING3.  If not see
   /* cbrt(expN(x)) -> expN(x/3).  */
   (simplify
    (cbrts (exps @0))
-   (exps (mult @0 { build_real_truncate (type, dconst_third ()); })))))
+   (exps (mult @0 { build_real_truncate (type, dconst_third ()); })))
+  /* pow(expN(x), y) -> expN(x*y).  */
+  (simplify
+   (pows (exps @0) @1)
+   (exps (mult @0 @1))))
+
+ /* tan(atan(x)) -> x.  */
+ (for tans (TAN)
+      atans (ATAN)
+  (simplify
+   (tans (atans @0))
+   @0)))
+
+/* cabs(x+0i) or cabs(0+xi) -> abs(x).  */
+(simplify
+ (CABS (complex:C @0 real_zerop@1))
+ (abs @0))
+
+/* trunc(trunc(x)) -> trunc(x), etc.  */
+(for fns (TRUNC FLOOR CEIL ROUND NEARBYINT RINT)
+ (simplify
+  (fns (fns @0))
+  (fns @0)))
+/* f(x) -> x if x is integer valued and f does nothing for such values.  */
+(for fns (TRUNC FLOOR CEIL ROUND NEARBYINT RINT)
+ (simplify
+  (fns integer_valued_real_p@0)
+  @0))
+
+/* hypot(x,0) and hypot(0,x) -> abs(x).  */
+(simplify
+ (HYPOT:c @0 real_zerop@1)
+ (abs @0))
+
+/* pow(1,x) -> 1.  */
+(simplify
+ (POW real_onep@0 @1)
+ @0)
+
+(simplify
+ /* copysign(x,x) -> x.  */
+ (COPYSIGN @0 @0)
+ @0)
+
+(simplify
+ /* copysign(x,y) -> fabs(x) if y is nonnegative.  */
+ (COPYSIGN @0 tree_expr_nonnegative_p@1)
+ (abs @0))
+
+(for scale (LDEXP SCALBN SCALBLN)
+ /* ldexp(0, x) -> 0.  */
+ (simplify
+  (scale real_zerop@0 @1)
+  @0)
+ /* ldexp(x, 0) -> x.  */
+ (simplify
+  (scale @0 integer_zerop@1)
+  @0)
+ /* ldexp(x, y) -> x if x is +-Inf or NaN.  */
+ (simplify
+  (scale REAL_CST@0 @1)
+  (if (!real_isfinite (TREE_REAL_CST_PTR (@0)))
+   @0)))
 
 /* Canonicalization of sequences of math builtins.  These rules represent
    IL simplifications but are not necessarily optimizations.
@@ -2284,7 +2989,7 @@ along with GCC; see the file COPYING3.  If not see
 
  /* Simplify x * pow(x,c) -> pow(x,c+1). */
  (simplify
-  (mult @0 (POW:s @0 REAL_CST@1))
+  (mult:c @0 (POW:s @0 REAL_CST@1))
   (if (!TREE_OVERFLOW (@1))
    (POW @0 (plus @1 { build_one_cst (type); }))))
 
@@ -2303,7 +3008,7 @@ along with GCC; see the file COPYING3.  If not see
   (rdiv (SIN:s @0) (TAN:s @0))
   (if (! HONOR_NANS (@0)
        && ! HONOR_INFINITIES (@0))
-   (cos @0)))
+   (COS @0)))
 
  /* Simplify tan(x) / sin(x) -> 1.0 / cos(x). */
  (simplify
@@ -2322,6 +3027,11 @@ along with GCC; see the file COPYING3.  If not see
   (mult (POW:s @0 @1) (POW:s @2 @1))
    (POW (mult @0 @2) @1))
 
+ /* Simplify powi(x,y) * powi(z,y) -> powi(x*z,y). */
+ (simplify
+  (mult (POWI:s @0 @1) (POWI:s @2 @1))
+   (POWI (mult @0 @2) @1))
+
  /* Simplify pow(x,c) / x -> pow(x,c-1). */
  (simplify
   (rdiv (POW:s @0 REAL_CST@1) @0)
@@ -2359,7 +3069,219 @@ along with GCC; see the file COPYING3.  If not see
   /* cbrt(pow(x,y)) -> pow(x,y/3), iff x is nonnegative.  */
   (simplify
    (cbrts (pows tree_expr_nonnegative_p@0 @1))
-   (pows @0 (mult @1 { build_real_truncate (type, dconst_third ()); })))))
+   (pows @0 (mult @1 { build_real_truncate (type, dconst_third ()); })))
+  /* pow(sqrt(x),y) -> pow(x,y*0.5).  */
+  (simplify
+   (pows (sqrts @0) @1)
+   (pows @0 (mult @1 { build_real (type, dconsthalf); })))
+  /* pow(cbrt(x),y) -> pow(x,y/3) iff x is nonnegative.  */
+  (simplify
+   (pows (cbrts tree_expr_nonnegative_p@0) @1)
+   (pows @0 (mult @1 { build_real_truncate (type, dconst_third ()); })))
+  /* pow(pow(x,y),z) -> pow(x,y*z) iff x is nonnegative.  */
+  (simplify
+   (pows (pows tree_expr_nonnegative_p@0 @1) @2)
+   (pows @0 (mult @1 @2))))
+
+ /* cabs(x+xi) -> fabs(x)*sqrt(2).  */
+ (simplify
+  (CABS (complex @0 @0))
+  (mult (abs @0) { build_real_truncate (type, dconst_sqrt2 ()); }))
+
+ /* hypot(x,x) -> fabs(x)*sqrt(2).  */
+ (simplify
+  (HYPOT @0 @0)
+  (mult (abs @0) { build_real_truncate (type, dconst_sqrt2 ()); }))
+
+ /* cexp(x+yi) -> exp(x)*cexpi(y).  */
+ (for cexps (CEXP)
+      exps (EXP)
+      cexpis (CEXPI)
+  (simplify
+   (cexps compositional_complex@0)
+   (if (targetm.libc_has_function (function_c99_math_complex))
+    (complex
+     (mult (exps@1 (realpart @0)) (realpart (cexpis:type@2 (imagpart @0))))
+     (mult @1 (imagpart @2)))))))
+
+(if (canonicalize_math_p ())
+ /* floor(x) -> trunc(x) if x is nonnegative.  */
+ (for floors (FLOOR)
+      truncs (TRUNC)
+  (simplify
+   (floors tree_expr_nonnegative_p@0)
+   (truncs @0))))
+
+(match double_value_p
+ @0
+ (if (TYPE_MAIN_VARIANT (TREE_TYPE (@0)) == double_type_node)))
+(for froms (BUILT_IN_TRUNCL
+           BUILT_IN_FLOORL
+           BUILT_IN_CEILL
+           BUILT_IN_ROUNDL
+           BUILT_IN_NEARBYINTL
+           BUILT_IN_RINTL)
+     tos (BUILT_IN_TRUNC
+         BUILT_IN_FLOOR
+         BUILT_IN_CEIL
+         BUILT_IN_ROUND
+         BUILT_IN_NEARBYINT
+         BUILT_IN_RINT)
+ /* truncl(extend(x)) -> extend(trunc(x)), etc., if x is a double.  */
+ (if (optimize && canonicalize_math_p ())
+  (simplify
+   (froms (convert double_value_p@0))
+   (convert (tos @0)))))
+
+(match float_value_p
+ @0
+ (if (TYPE_MAIN_VARIANT (TREE_TYPE (@0)) == float_type_node)))
+(for froms (BUILT_IN_TRUNCL BUILT_IN_TRUNC
+           BUILT_IN_FLOORL BUILT_IN_FLOOR
+           BUILT_IN_CEILL BUILT_IN_CEIL
+           BUILT_IN_ROUNDL BUILT_IN_ROUND
+           BUILT_IN_NEARBYINTL BUILT_IN_NEARBYINT
+           BUILT_IN_RINTL BUILT_IN_RINT)
+     tos (BUILT_IN_TRUNCF BUILT_IN_TRUNCF
+         BUILT_IN_FLOORF BUILT_IN_FLOORF
+         BUILT_IN_CEILF BUILT_IN_CEILF
+         BUILT_IN_ROUNDF BUILT_IN_ROUNDF
+         BUILT_IN_NEARBYINTF BUILT_IN_NEARBYINTF
+         BUILT_IN_RINTF BUILT_IN_RINTF)
+ /* truncl(extend(x)) and trunc(extend(x)) -> extend(truncf(x)), etc.,
+    if x is a float.  */
+ (if (optimize && canonicalize_math_p ()
+      && targetm.libc_has_function (function_c99_misc))
+  (simplify
+   (froms (convert float_value_p@0))
+   (convert (tos @0)))))
+
+(for froms (XFLOORL XCEILL XROUNDL XRINTL)
+     tos (XFLOOR XCEIL XROUND XRINT)
+ /* llfloorl(extend(x)) -> llfloor(x), etc., if x is a double.  */
+ (if (optimize && canonicalize_math_p ())
+  (simplify
+   (froms (convert double_value_p@0))
+   (tos @0))))
+
+(for froms (XFLOORL XCEILL XROUNDL XRINTL
+           XFLOOR XCEIL XROUND XRINT)
+     tos (XFLOORF XCEILF XROUNDF XRINTF)
+ /* llfloorl(extend(x)) and llfloor(extend(x)) -> llfloorf(x), etc.,
+    if x is a float.  */
+ (if (optimize && canonicalize_math_p ())
+  (simplify
+   (froms (convert float_value_p@0))
+   (tos @0))))
+
+(if (canonicalize_math_p ())
+ /* xfloor(x) -> fix_trunc(x) if x is nonnegative.  */
+ (for floors (IFLOOR LFLOOR LLFLOOR)
+  (simplify
+   (floors tree_expr_nonnegative_p@0)
+   (fix_trunc @0))))
+
+(if (canonicalize_math_p ())
+ /* xfloor(x) -> fix_trunc(x), etc., if x is integer valued.  */
+ (for fns (IFLOOR LFLOOR LLFLOOR
+          ICEIL LCEIL LLCEIL
+          IROUND LROUND LLROUND)
+  (simplify
+   (fns integer_valued_real_p@0)
+   (fix_trunc @0)))
+ (if (!flag_errno_math)
+  /* xrint(x) -> fix_trunc(x), etc., if x is integer valued.  */
+  (for rints (IRINT LRINT LLRINT)
+   (simplify
+    (rints integer_valued_real_p@0)
+    (fix_trunc @0)))))
+
+(if (canonicalize_math_p ())
+ (for ifn (IFLOOR ICEIL IROUND IRINT)
+      lfn (LFLOOR LCEIL LROUND LRINT)
+      llfn (LLFLOOR LLCEIL LLROUND LLRINT)
+  /* Canonicalize iround (x) to lround (x) on ILP32 targets where
+     sizeof (int) == sizeof (long).  */
+  (if (TYPE_PRECISION (integer_type_node)
+       == TYPE_PRECISION (long_integer_type_node))
+   (simplify
+    (ifn @0)
+    (lfn:long_integer_type_node @0)))
+  /* Canonicalize llround (x) to lround (x) on LP64 targets where
+     sizeof (long long) == sizeof (long).  */
+  (if (TYPE_PRECISION (long_long_integer_type_node)
+       == TYPE_PRECISION (long_integer_type_node))
+   (simplify
+    (llfn @0)
+    (lfn:long_integer_type_node @0)))))
+
+/* cproj(x) -> x if we're ignoring infinities.  */
+(simplify
+ (CPROJ @0)
+ (if (!HONOR_INFINITIES (type))
+   @0))
+
+/* If the real part is inf and the imag part is known to be
+   nonnegative, return (inf + 0i).  */
+(simplify
+ (CPROJ (complex REAL_CST@0 tree_expr_nonnegative_p@1))
+ (if (real_isinf (TREE_REAL_CST_PTR (@0)))
+  { build_complex_inf (type, false); }))
+
+/* If the imag part is inf, return (inf+I*copysign(0,imag)).  */
+(simplify
+ (CPROJ (complex @0 REAL_CST@1))
+ (if (real_isinf (TREE_REAL_CST_PTR (@1)))
+  { build_complex_inf (type, TREE_REAL_CST_PTR (@1)->sign); }))
+
+(for pows (POW)
+     sqrts (SQRT)
+     cbrts (CBRT)
+ (simplify
+  (pows @0 REAL_CST@1)
+  (with {
+    const REAL_VALUE_TYPE *value = TREE_REAL_CST_PTR (@1);
+    REAL_VALUE_TYPE tmp;
+   }
+   (switch
+    /* pow(x,0) -> 1.  */
+    (if (real_equal (value, &dconst0))
+     { build_real (type, dconst1); })
+    /* pow(x,1) -> x.  */
+    (if (real_equal (value, &dconst1))
+     @0)
+    /* pow(x,-1) -> 1/x.  */
+    (if (real_equal (value, &dconstm1))
+     (rdiv { build_real (type, dconst1); } @0))
+    /* pow(x,0.5) -> sqrt(x).  */
+    (if (flag_unsafe_math_optimizations
+        && canonicalize_math_p ()
+        && real_equal (value, &dconsthalf))
+     (sqrts @0))
+    /* pow(x,1/3) -> cbrt(x).  */
+    (if (flag_unsafe_math_optimizations
+        && canonicalize_math_p ()
+        && (tmp = real_value_truncate (TYPE_MODE (type), dconst_third ()),
+            real_equal (value, &tmp)))
+     (cbrts @0))))))
+
+/* powi(1,x) -> 1.  */
+(simplify
+ (POWI real_onep@0 @1)
+ @0)
+
+(simplify
+ (POWI @0 INTEGER_CST@1)
+ (switch
+  /* powi(x,0) -> 1.  */
+  (if (wi::eq_p (@1, 0))
+   { build_real (type, dconst1); })
+  /* powi(x,1) -> x.  */
+  (if (wi::eq_p (@1, 1))
+   @0)
+  /* powi(x,-1) -> 1/x.  */
+  (if (wi::eq_p (@1, -1))
+   (rdiv { build_real (type, dconst1); } @0))))
 
 /* Narrowing of arithmetic and logical operations. 
 
@@ -2370,11 +3292,11 @@ along with GCC; see the file COPYING3.  If not see
 /* If we have a narrowing conversion of an arithmetic operation where
    both operands are widening conversions from the same type as the outer
    narrowing conversion.  Then convert the innermost operands to a suitable
-   unsigned type (to avoid introducing undefined behaviour), perform the
+   unsigned type (to avoid introducing undefined behavior), perform the
    operation and convert the result to the desired type.  */
 (for op (plus minus)
   (simplify
-    (convert (op:s (convert@2 @0) (convert@3 @1)))
+    (convert (op:s (convert@2 @0) (convert?@3 @1)))
     (if (INTEGRAL_TYPE_P (type)
         /* We check for type compatibility between @0 and @1 below,
            so there's no need to check that @1/@3 are integral types.  */
@@ -2390,17 +3312,21 @@ along with GCC; see the file COPYING3.  If not see
         && TYPE_PRECISION (type) == GET_MODE_PRECISION (TYPE_MODE (type))
         /* The inner conversion must be a widening conversion.  */
         && TYPE_PRECISION (TREE_TYPE (@2)) > TYPE_PRECISION (TREE_TYPE (@0))
-        && types_match (@0, @1)
-        && types_match (@0, type))
+        && types_match (@0, type)
+        && (types_match (@0, @1)
+            /* Or the second operand is const integer or converted const
+               integer from valueize.  */
+            || TREE_CODE (@1) == INTEGER_CST))
       (if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
-       (convert (op @0 @1))
+       (op @0 (convert @1))
        (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); }
-        (convert (op (convert:utype @0) (convert:utype @1))))))))
+        (convert (op (convert:utype @0)
+                     (convert:utype @1))))))))
 
 /* This is another case of narrowing, specifically when there's an outer
    BIT_AND_EXPR which masks off bits outside the type of the innermost
    operands.   Like the previous case we have to convert the operands
-   to unsigned types to avoid introducing undefined behaviour for the
+   to unsigned types to avoid introducing undefined behavior for the
    arithmetic operation.  */
 (for op (minus plus)
  (simplify
@@ -2423,11 +3349,174 @@ along with GCC; see the file COPYING3.  If not see
        && types_match (@0, @1)
        && (tree_int_cst_min_precision (@4, TYPE_SIGN (TREE_TYPE (@0)))
           <= TYPE_PRECISION (TREE_TYPE (@0)))
-       && (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))
-          || tree_int_cst_sgn (@4) >= 0))
+       && (wi::bit_and (@4, wi::mask (TYPE_PRECISION (TREE_TYPE (@0)),
+                       true, TYPE_PRECISION (type))) == 0))
    (if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
     (with { tree ntype = TREE_TYPE (@0); }
      (convert (bit_and (op @0 @1) (convert:ntype @4))))
     (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); }
      (convert (bit_and (op (convert:utype @0) (convert:utype @1))
               (convert:utype @4))))))))
+
+/* Transform (@0 < @1 and @0 < @2) to use min, 
+   (@0 > @1 and @0 > @2) to use max */
+(for op (lt le gt ge)
+     ext (min min max max)
+ (simplify
+  (bit_and (op:cs @0 @1) (op:cs @0 @2))
+  (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+       && TREE_CODE (@0) != INTEGER_CST)
+   (op @0 (ext @1 @2)))))
+
+(simplify
+ /* signbit(x) -> 0 if x is nonnegative.  */
+ (SIGNBIT tree_expr_nonnegative_p@0)
+ { integer_zero_node; })
+
+(simplify
+ /* signbit(x) -> x<0 if x doesn't have signed zeros.  */
+ (SIGNBIT @0)
+ (if (!HONOR_SIGNED_ZEROS (@0))
+  (convert (lt @0 { build_real (TREE_TYPE (@0), dconst0); }))))
+
+/* Transform comparisons of the form X +- C1 CMP C2 to X CMP C2 -+ C1.  */
+(for cmp (eq ne)
+ (for op (plus minus)
+      rop (minus plus)
+  (simplify
+   (cmp (op@3 @0 INTEGER_CST@1) INTEGER_CST@2)
+   (if (!TREE_OVERFLOW (@1) && !TREE_OVERFLOW (@2)
+       && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@0))
+       && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (@0))
+       && !TYPE_SATURATING (TREE_TYPE (@0)))
+    (with { tree res = int_const_binop (rop, @2, @1); }
+     (if (TREE_OVERFLOW (res))
+      { constant_boolean_node (cmp == NE_EXPR, type); }
+      (if (single_use (@3))
+       (cmp @0 { res; }))))))))
+(for cmp (lt le gt ge)
+ (for op (plus minus)
+      rop (minus plus)
+  (simplify
+   (cmp (op@3 @0 INTEGER_CST@1) INTEGER_CST@2)
+   (if (!TREE_OVERFLOW (@1) && !TREE_OVERFLOW (@2)
+       && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
+    (with { tree res = int_const_binop (rop, @2, @1); }
+     (if (TREE_OVERFLOW (res))
+      {
+       fold_overflow_warning (("assuming signed overflow does not occur "
+                               "when simplifying conditional to constant"),
+                              WARN_STRICT_OVERFLOW_CONDITIONAL);
+        bool less = cmp == LE_EXPR || cmp == LT_EXPR;
+       /* wi::ges_p (@2, 0) should be sufficient for a signed type.  */
+       bool ovf_high = wi::lt_p (@1, 0, TYPE_SIGN (TREE_TYPE (@1)))
+                       != (op == MINUS_EXPR);
+       constant_boolean_node (less == ovf_high, type);
+      }
+      (if (single_use (@3))
+       (with
+       {
+         fold_overflow_warning (("assuming signed overflow does not occur "
+                                 "when changing X +- C1 cmp C2 to "
+                                 "X cmp C2 -+ C1"),
+                                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); })))))))))
This page took 0.070497 seconds and 5 git commands to generate.