diff options
author | Jeff Law <law@redhat.com> | 2015-02-13 13:17:55 -0700 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 2015-02-13 13:17:55 -0700 |
commit | be1448389ab3038cccba3ed99e157bd6842ef88f (patch) | |
tree | 79bec4c1dc64b01a597c72371d5e618363458405 | |
parent | d05022766b7e692567e24198d44b91253c4a2625 (diff) | |
download | gcc-be1448389ab3038cccba3ed99e157bd6842ef88f.zip gcc-be1448389ab3038cccba3ed99e157bd6842ef88f.tar.gz gcc-be1448389ab3038cccba3ed99e157bd6842ef88f.tar.bz2 |
re PR rtl-optimization/47477 (Sub-optimal mov at end of method)
PR rtl-optimization/47477
* match.pd (convert (plus/minus (convert @0) (convert @1): New
simplifier to narrow arithmetic.
PR rtl-optimization/47477
* gcc.dg/tree-ssa/pr47477.c: New test.
From-SVN: r220695
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/match.pd | 41 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/pr47477.c | 22 |
4 files changed, 74 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 290d3ac..f36e16c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2015-02-13 Jeff Law <law@redhat.com> + + PR rtl-optimization/47477 + * match.pd (convert (plus/minus (convert @0) (convert @1): New + simplifier to narrow arithmetic. + 2015-02-13 Jan Hubicka <hubicka@ucw.cz> PR ipa/65028 diff --git a/gcc/match.pd b/gcc/match.pd index 81c4ee6..d438179 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -1018,3 +1018,44 @@ along with GCC; see the file COPYING3. If not see (logs (pows @0 @1)) (mult @1 (logs @0))))) +/* Narrowing of arithmetic and logical operations. + + These are conceptually similar to the transformations performed for + the C/C++ front-ends by shorten_binary_op and shorten_compare. Long + term we want to move all that code out of the front-ends into here. */ + +/* 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 + operation and convert the result to the desired type. */ +(for op (plus minus) + (simplify + (convert (op (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. */ + && INTEGRAL_TYPE_P (TREE_TYPE (@0)) + && INTEGRAL_TYPE_P (TREE_TYPE (@2)) + /* The precision of the type of each operand must match the + precision of the mode of each operand, similarly for the + result. */ + && (TYPE_PRECISION (TREE_TYPE (@0)) + == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (@0)))) + && (TYPE_PRECISION (TREE_TYPE (@1)) + == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (@1)))) + && 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)) + && ((GENERIC + && (TYPE_MAIN_VARIANT (TREE_TYPE (@0)) + == TYPE_MAIN_VARIANT (TREE_TYPE (@1))) + && (TYPE_MAIN_VARIANT (TREE_TYPE (@0)) + == TYPE_MAIN_VARIANT (type))) + || (GIMPLE + && types_compatible_p (TREE_TYPE (@0), TREE_TYPE (@1)) + && types_compatible_p (TREE_TYPE (@0), type)))) + (if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))) + (convert (op @0 @1))) + (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); } + (convert (op (convert:utype @0) (convert:utype @1))))))) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b2d1c11..2fe9698 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-02-13 Jeff Law <law@redhat.com> + + PR rtl-optimization/47477 + * gcc.dg/tree-ssa/pr47477.c: New test. + 2015-02-13 Paolo Carlini <paolo.carlini@oracle.com> PR c++/60211 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr47477.c b/gcc/testsuite/gcc.dg/tree-ssa/pr47477.c new file mode 100644 index 0000000..104cb6f5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr47477.c @@ -0,0 +1,22 @@ +/* PR tree-optimization/47477 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized -w" } */ +/* { dg-require-effective-target ilp32 } */ + +typedef int int64_t __attribute__ ((__mode__ (__DI__))); +typedef int * intptr_t; + +typedef struct toto_s *toto_t; +toto_t add (toto_t a, toto_t b) { + int64_t tmp = (int64_t)(intptr_t)a + ((int64_t)(intptr_t)b&~1L); + return (toto_t)(intptr_t) tmp; +} + +/* For an ILP32 target there'll be 6 casts when we start, but just 4 + if the match.pd pattern is successfully matched. */ +/* { dg-final { scan-tree-dump-times "= \\(int\\)" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "= \\(unsigned int\\)" 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "= \\(struct toto_s \\*\\)" 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + + |