This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFA][PATCH][PR rtl-optimization/47477] Type narrowing in match.pd


On 02/12/15 06:02, Richard Biener wrote:


No strong opinion on separate pattern or integrating into existing pattern.

Yeah, I'd leave it as you did it for now.  Btw, -ENOPATCH.
This version should address all your comments.  A few notes.

When in GENERIC, the inner operands can be a fairly arbitrary expression, including things like COMPONENT_REFs for bitfields. We filter these out by ensuring the type's precision for both operands is a power of two and at least byte sized.

It may not be strictly necessary, but the pattern now verifies that the final type, type of the inner conversion and type of the @0/@1 arguments are integral types. Just seemed like the safe thing to do.

I added the TYPE_OVERFLOW_WRAPS support into the new pattern rather than create a totally new pattern.

Testcase name change to reflect it's actually from a PR.

Bootstrapped and regression tested on x86_64-unknown-linux-gnu. OK for the trunk?

Jeff
commit a0317dfd4a3f7fc907a84e6956a8c116bb941f52
Author: Jeff Law <law@redhat.com>
Date:   Wed Feb 11 16:19:05 2015 -0700

    	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.

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c9ac045..1258a0a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,11 @@
 2015-02-11  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-11  Jeff Law  <law@redhat.com>
+
 	PR target/63347
 	* haifa-sched.c (prune_ready_list): If we have a SCHED_GROUP_P insn
 	that needs to be queued, just queue it for a single cycle.
diff --git a/gcc/match.pd b/gcc/match.pd
index 81c4ee6..27e0dd2 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -1018,3 +1018,36 @@ 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 (((GENERIC 
+	   && TYPE_MAIN_VARIANT (TREE_TYPE (@0)) == TYPE_MAIN_VARIANT (type)
+	   /* @0 and @1 could be arbitrary expressions here, including 
+	      COMPONENT_REFs with inconvenient types.  For example, they
+	      might have a TYPE_PRECISION of 15 bits.  Ensure we are working
+	      with TYPE_PRECISION that are powers of two and at least byte
+	      sized.  */
+	   && exact_log2 (TYPE_PRECISION (TREE_TYPE (@0))) >= 3
+	   && exact_log2 (TYPE_PRECISION (TREE_TYPE (@1))) >= 3)
+	  || (GIMPLE && types_compatible_p (TREE_TYPE (@0), TREE_TYPE (@1))))
+	 && TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (type)
+	 && INTEGRAL_TYPE_P (type)
+	 && INTEGRAL_TYPE_P (TREE_TYPE (@0))
+	 && INTEGRAL_TYPE_P (TREE_TYPE (@2))
+	 && TYPE_PRECISION (TREE_TYPE (@2)) > TYPE_PRECISION (TREE_TYPE (@0)))
+      (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 8d5d3f3..2455c68 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2015-02-11  Jeff Law  <law@redhat.com>
+
+	PR rtl-optimization/47477
+	* gcc.dg/tree-ssa/pr47477.c: New test.
+
 2015-02-11  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
 
 	PR libgfortran/57822
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" } } */
+
+

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]