[PATCH][2/2] Fix PR81502
Richard Biener
rguenther@suse.de
Thu Jul 27 13:51:00 GMT 2017
I am testing the following additional pattern for match.pd to fix
PR81502 resulting in the desired optimization to
bar:
.LFB526:
.cfi_startproc
movl %edi, %eax
ret
the pattern optimizes a BIT_FIELD_REF on a BIT_INSERT_EXPR by
either extracting from the destination or the inserted value.
Bootstrap and regtest running on x86_64-unknown-linux-gnu.
Richard.
2017-07-27 Richard Biener <rguenther@suse.de>
PR tree-optimization/81502
* match.pd: Add pattern combining BIT_INSERT_EXPR with
BIT_FIELD_REF.
* gcc.target/i386/pr81502.c: New testcase.
Index: gcc/match.pd
===================================================================
*** gcc/match.pd (revision 250620)
--- gcc/match.pd (working copy)
*************** DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
*** 4178,4180 ****
--- 4178,4195 ----
{ CONSTRUCTOR_ELT (ctor, idx / k)->value; })
(BIT_FIELD_REF { CONSTRUCTOR_ELT (ctor, idx / k)->value; }
@1 { bitsize_int ((idx % k) * width); })))))))))
+
+ /* Simplify a bit extraction from a bit insertion for the cases with
+ the inserted element fully covering the extraction or the insertion
+ not touching the extraction. */
+ (simplify
+ (BIT_FIELD_REF (bit_insert @0 @1 @ipos) @rsize @rpos)
+ (switch
+ (if (wi::leu_p (@ipos, @rpos)
+ && wi::leu_p (wi::add (@rpos, @rsize),
+ wi::add (@ipos, TYPE_PRECISION (TREE_TYPE (@1)))))
+ (BIT_FIELD_REF @1 @rsize { wide_int_to_tree (bitsizetype,
+ wi::sub (@rpos, @ipos)); }))
+ (if (wi::geu_p (@ipos, wi::add (@rpos, @rsize))
+ || wi::geu_p (@rpos, wi::add (@ipos, TYPE_PRECISION (TREE_TYPE (@1)))))
+ (BIT_FIELD_REF @0 @rsize @rpos))))
Index: gcc/testsuite/gcc.target/i386/pr81502.c
===================================================================
*** gcc/testsuite/gcc.target/i386/pr81502.c (nonexistent)
--- gcc/testsuite/gcc.target/i386/pr81502.c (working copy)
***************
*** 0 ****
--- 1,34 ----
+ /* { dg-do compile { target lp64 } } */
+ /* { dg-options "-O2 -msse2" } */
+
+ #include <emmintrin.h>
+
+ #define SIZE (sizeof (void *))
+
+ static int foo(unsigned char (*foo)[SIZE])
+ {
+ __m128i acc = _mm_set_epi32(0, 0, 0, 0);
+ size_t i = 0;
+ for(; i + sizeof(__m128i) <= SIZE; i += sizeof(__m128i)) {
+ __m128i word;
+ __builtin_memcpy(&word, foo + i, sizeof(__m128i));
+ acc = _mm_add_epi32(word, acc);
+ }
+ if (i != SIZE) {
+ __m128i word = _mm_set_epi32(0, 0, 0, 0);
+ __builtin_memcpy(&word, foo + i, SIZE - i); // (1)
+ acc = _mm_add_epi32(word, acc);
+ }
+ int res;
+ __builtin_memcpy(&res, &acc, sizeof(res));
+ return res;
+ }
+
+ int bar(void *ptr)
+ {
+ unsigned char buf[SIZE];
+ __builtin_memcpy(buf, &ptr, SIZE);
+ return foo((unsigned char(*)[SIZE])buf);
+ }
+
+ /* { dg-final { scan-assembler-times "mov" 1 } } */
More information about the Gcc-patches
mailing list