198 lines
7.2 KiB
Diff
198 lines
7.2 KiB
Diff
|
|
This backport contains 2 patch from gcc main stream tree.
|
|||
|
|
The commit id of these patchs list as following in the order of time.
|
|||
|
|
|
|||
|
|
0001-Simplify-X-C1-C2-with-undefined-overflow.patch
|
|||
|
|
ca2b8c082c4f16919071c9f8de8db0b33b54c405
|
|||
|
|
|
|||
|
|
0002-Simplify-X-C1-C2-with-wrapping-overflow.patch
|
|||
|
|
287522613d661b4c5ba8403b051eb470c1674cba
|
|||
|
|
|
|||
|
|
diff -Nurp a/gcc/expr.c b/gcc/expr.c
|
|||
|
|
--- a/gcc/expr.c 2021-03-17 16:34:24.700000000 +0800
|
|||
|
|
+++ b/gcc/expr.c 2021-03-17 10:30:11.500000000 +0800
|
|||
|
|
@@ -11706,38 +11706,6 @@ string_constant (tree arg, tree *ptr_off
|
|||
|
|
return init;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
-/* Compute the modular multiplicative inverse of A modulo M
|
|||
|
|
- using extended Euclid's algorithm. Assumes A and M are coprime. */
|
|||
|
|
-static wide_int
|
|||
|
|
-mod_inv (const wide_int &a, const wide_int &b)
|
|||
|
|
-{
|
|||
|
|
- /* Verify the assumption. */
|
|||
|
|
- gcc_checking_assert (wi::eq_p (wi::gcd (a, b), 1));
|
|||
|
|
-
|
|||
|
|
- unsigned int p = a.get_precision () + 1;
|
|||
|
|
- gcc_checking_assert (b.get_precision () + 1 == p);
|
|||
|
|
- wide_int c = wide_int::from (a, p, UNSIGNED);
|
|||
|
|
- wide_int d = wide_int::from (b, p, UNSIGNED);
|
|||
|
|
- wide_int x0 = wide_int::from (0, p, UNSIGNED);
|
|||
|
|
- wide_int x1 = wide_int::from (1, p, UNSIGNED);
|
|||
|
|
-
|
|||
|
|
- if (wi::eq_p (b, 1))
|
|||
|
|
- return wide_int::from (1, p, UNSIGNED);
|
|||
|
|
-
|
|||
|
|
- while (wi::gt_p (c, 1, UNSIGNED))
|
|||
|
|
- {
|
|||
|
|
- wide_int t = d;
|
|||
|
|
- wide_int q = wi::divmod_trunc (c, d, UNSIGNED, &d);
|
|||
|
|
- c = t;
|
|||
|
|
- wide_int s = x0;
|
|||
|
|
- x0 = wi::sub (x1, wi::mul (q, x0));
|
|||
|
|
- x1 = s;
|
|||
|
|
- }
|
|||
|
|
- if (wi::lt_p (x1, 0, SIGNED))
|
|||
|
|
- x1 += d;
|
|||
|
|
- return x1;
|
|||
|
|
-}
|
|||
|
|
-
|
|||
|
|
/* Optimize x % C1 == C2 for signed modulo if C1 is a power of two and C2
|
|||
|
|
is non-zero and C3 ((1<<(prec-1)) | (C1 - 1)):
|
|||
|
|
for C2 > 0 to x & C3 == C2
|
|||
|
|
@@ -11948,7 +11916,7 @@ maybe_optimize_mod_cmp (enum tree_code c
|
|||
|
|
w = wi::lrshift (w, shift);
|
|||
|
|
wide_int a = wide_int::from (w, prec + 1, UNSIGNED);
|
|||
|
|
wide_int b = wi::shifted_mask (prec, 1, false, prec + 1);
|
|||
|
|
- wide_int m = wide_int::from (mod_inv (a, b), prec, UNSIGNED);
|
|||
|
|
+ wide_int m = wide_int::from (wi::mod_inv (a, b), prec, UNSIGNED);
|
|||
|
|
tree c3 = wide_int_to_tree (type, m);
|
|||
|
|
tree c5 = NULL_TREE;
|
|||
|
|
wide_int d, e;
|
|||
|
|
diff -Nurp a/gcc/match.pd b/gcc/match.pd
|
|||
|
|
--- a/gcc/match.pd 2021-03-17 16:34:19.320000000 +0800
|
|||
|
|
+++ b/gcc/match.pd 2021-03-17 10:30:11.500000000 +0800
|
|||
|
|
@@ -3290,6 +3290,35 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
|
|||
|
|
(scmp @0 @2)
|
|||
|
|
(cmp @0 @2))))))
|
|||
|
|
|
|||
|
|
+/* For integral types with undefined overflow fold
|
|||
|
|
+ x * C1 == C2 into x == C2 / C1 or false.
|
|||
|
|
+ If overflow wraps and C1 is odd, simplify to x == C2 / C1 in the ring
|
|||
|
|
+ Z / 2^n Z. */
|
|||
|
|
+(for cmp (eq ne)
|
|||
|
|
+ (simplify
|
|||
|
|
+ (cmp (mult @0 INTEGER_CST@1) INTEGER_CST@2)
|
|||
|
|
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
|
|||
|
|
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))
|
|||
|
|
+ && wi::to_wide (@1) != 0)
|
|||
|
|
+ (with { widest_int quot; }
|
|||
|
|
+ (if (wi::multiple_of_p (wi::to_widest (@2), wi::to_widest (@1),
|
|||
|
|
+ TYPE_SIGN (TREE_TYPE (@0)), "))
|
|||
|
|
+ (cmp @0 { wide_int_to_tree (TREE_TYPE (@0), quot); })
|
|||
|
|
+ { constant_boolean_node (cmp == NE_EXPR, type); }))
|
|||
|
|
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
|
|||
|
|
+ && TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))
|
|||
|
|
+ && (wi::bit_and (wi::to_wide (@1), 1) == 1))
|
|||
|
|
+ (cmp @0
|
|||
|
|
+ {
|
|||
|
|
+ tree itype = TREE_TYPE (@0);
|
|||
|
|
+ int p = TYPE_PRECISION (itype);
|
|||
|
|
+ wide_int m = wi::one (p + 1) << p;
|
|||
|
|
+ wide_int a = wide_int::from (wi::to_wide (@1), p + 1, UNSIGNED);
|
|||
|
|
+ wide_int i = wide_int::from (wi::mod_inv (a, m),
|
|||
|
|
+ p, TYPE_SIGN (itype));
|
|||
|
|
+ wide_int_to_tree (itype, wi::mul (i, wi::to_wide (@2)));
|
|||
|
|
+ })))))
|
|||
|
|
+
|
|||
|
|
/* Simplify comparison of something with itself. For IEEE
|
|||
|
|
floating-point, we can only do some of these simplifications. */
|
|||
|
|
(for cmp (eq ge le)
|
|||
|
|
diff -Nurp a/gcc/testsuite/gcc.c-torture/execute/pr23135.c b/gcc/testsuite/gcc.c-torture/execute/pr23135.c
|
|||
|
|
--- a/gcc/testsuite/gcc.c-torture/execute/pr23135.c 2021-03-17 16:34:24.016000000 +0800
|
|||
|
|
+++ b/gcc/testsuite/gcc.c-torture/execute/pr23135.c 2021-03-17 10:30:13.572000000 +0800
|
|||
|
|
@@ -1,7 +1,7 @@
|
|||
|
|
/* Based on execute/simd-1.c, modified by joern.rennecke@st.com to
|
|||
|
|
trigger a reload bug. Verified for gcc mainline from 20050722 13:00 UTC
|
|||
|
|
for sh-elf -m4 -O2. */
|
|||
|
|
-/* { dg-options "-Wno-psabi" } */
|
|||
|
|
+/* { dg-options "-Wno-psabi -fwrapv" } */
|
|||
|
|
/* { dg-add-options stack_size } */
|
|||
|
|
|
|||
|
|
#ifndef STACK_SIZE
|
|||
|
|
diff -Nurp a/gcc/testsuite/gcc.dg/tree-ssa/pr95433-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr95433-2.c
|
|||
|
|
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr95433-2.c 1970-01-01 08:00:00.000000000 +0800
|
|||
|
|
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr95433-2.c 2021-03-17 10:30:13.276000000 +0800
|
|||
|
|
@@ -0,0 +1,15 @@
|
|||
|
|
+/* { dg-do compile } */
|
|||
|
|
+/* { dg-options "-O -fwrapv -fdump-tree-gimple" } */
|
|||
|
|
+
|
|||
|
|
+typedef __INT32_TYPE__ int32_t;
|
|||
|
|
+typedef unsigned __INT32_TYPE__ uint32_t;
|
|||
|
|
+
|
|||
|
|
+int e(int32_t x){return 3*x==5;}
|
|||
|
|
+int f(int32_t x){return 3*x==-5;}
|
|||
|
|
+int g(int32_t x){return -3*x==5;}
|
|||
|
|
+int h(int32_t x){return 7*x==3;}
|
|||
|
|
+int i(uint32_t x){return 7*x==3;}
|
|||
|
|
+
|
|||
|
|
+/* { dg-final { scan-tree-dump-times "== 1431655767" 1 "gimple" } } */
|
|||
|
|
+/* { dg-final { scan-tree-dump-times "== -1431655767" 2 "gimple" } } */
|
|||
|
|
+/* { dg-final { scan-tree-dump-times "== 613566757" 2 "gimple" } } */
|
|||
|
|
diff -Nurp a/gcc/testsuite/gcc.dg/tree-ssa/pr95433.c b/gcc/testsuite/gcc.dg/tree-ssa/pr95433.c
|
|||
|
|
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr95433.c 1970-01-01 08:00:00.000000000 +0800
|
|||
|
|
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr95433.c 2021-03-17 10:30:13.276000000 +0800
|
|||
|
|
@@ -0,0 +1,8 @@
|
|||
|
|
+/* { dg-do compile } */
|
|||
|
|
+/* { dg-options "-O -fdump-tree-optimized" } */
|
|||
|
|
+
|
|||
|
|
+int f(int x){return x*7==17;}
|
|||
|
|
+int g(int x){return x*3==15;}
|
|||
|
|
+
|
|||
|
|
+/* { dg-final { scan-tree-dump "return 0;" "optimized" } } */
|
|||
|
|
+/* { dg-final { scan-tree-dump "== 5;" "optimized" } } */
|
|||
|
|
diff -Nurp a/gcc/wide-int.cc b/gcc/wide-int.cc
|
|||
|
|
--- a/gcc/wide-int.cc 2021-03-17 16:34:24.488000000 +0800
|
|||
|
|
+++ b/gcc/wide-int.cc 2021-03-17 10:30:11.500000000 +0800
|
|||
|
|
@@ -2223,6 +2223,39 @@ wi::round_up_for_mask (const wide_int &v
|
|||
|
|
return (val | tmp) & -tmp;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
+/* Compute the modular multiplicative inverse of A modulo B
|
|||
|
|
+ using extended Euclid's algorithm. Assumes A and B are coprime,
|
|||
|
|
+ and that A and B have the same precision. */
|
|||
|
|
+wide_int
|
|||
|
|
+wi::mod_inv (const wide_int &a, const wide_int &b)
|
|||
|
|
+{
|
|||
|
|
+ /* Verify the assumption. */
|
|||
|
|
+ gcc_checking_assert (wi::eq_p (wi::gcd (a, b), 1));
|
|||
|
|
+
|
|||
|
|
+ unsigned int p = a.get_precision () + 1;
|
|||
|
|
+ gcc_checking_assert (b.get_precision () + 1 == p);
|
|||
|
|
+ wide_int c = wide_int::from (a, p, UNSIGNED);
|
|||
|
|
+ wide_int d = wide_int::from (b, p, UNSIGNED);
|
|||
|
|
+ wide_int x0 = wide_int::from (0, p, UNSIGNED);
|
|||
|
|
+ wide_int x1 = wide_int::from (1, p, UNSIGNED);
|
|||
|
|
+
|
|||
|
|
+ if (wi::eq_p (b, 1))
|
|||
|
|
+ return wide_int::from (1, p, UNSIGNED);
|
|||
|
|
+
|
|||
|
|
+ while (wi::gt_p (c, 1, UNSIGNED))
|
|||
|
|
+ {
|
|||
|
|
+ wide_int t = d;
|
|||
|
|
+ wide_int q = wi::divmod_trunc (c, d, UNSIGNED, &d);
|
|||
|
|
+ c = t;
|
|||
|
|
+ wide_int s = x0;
|
|||
|
|
+ x0 = wi::sub (x1, wi::mul (q, x0));
|
|||
|
|
+ x1 = s;
|
|||
|
|
+ }
|
|||
|
|
+ if (wi::lt_p (x1, 0, SIGNED))
|
|||
|
|
+ x1 += d;
|
|||
|
|
+ return x1;
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
/*
|
|||
|
|
* Private utilities.
|
|||
|
|
*/
|
|||
|
|
diff -Nurp a/gcc/wide-int.h b/gcc/wide-int.h
|
|||
|
|
--- a/gcc/wide-int.h 2021-03-17 16:34:14.792000000 +0800
|
|||
|
|
+++ b/gcc/wide-int.h 2021-03-17 10:30:11.500000000 +0800
|
|||
|
|
@@ -3368,6 +3368,8 @@ namespace wi
|
|||
|
|
wide_int round_down_for_mask (const wide_int &, const wide_int &);
|
|||
|
|
wide_int round_up_for_mask (const wide_int &, const wide_int &);
|
|||
|
|
|
|||
|
|
+ wide_int mod_inv (const wide_int &a, const wide_int &b);
|
|||
|
|
+
|
|||
|
|
template <typename T>
|
|||
|
|
T mask (unsigned int, bool);
|
|||
|
|
|