This patch is the backend piece of my proposed fix to PR tree-opt/98335,
to allow C++ partial struct initialization to be as efficient/optimized
as full struct initialization.

With the middle-end patch just posted to gcc-patches, the test case
in the PR compiles on x86_64-pc-linux-gnu with -O2 to:

        xorl    %eax, %eax
        movb    c(%rip), %al
        ret

with this additional peephole2 (actually pair of peephole2s):

        movzbl  c(%rip), %eax
        ret


This patch has been tested on x86_64-pc-linux-gnu, on top of the
middle-end piece, with make bootstrap and make -k check with no
new failures.  Posted in pieces to simplify review.  Ok for mainline?


2022-03-07  Roger Sayle  <ro...@nextmovesoftware.com>

gcc/ChangeLog
        PR tree-optimization/98335
        * config/i386/i386.md (peephole2): Transform xorl followed by
        a suitable movb or movw into the equivalent movz[bw]l.

gcc/testsuite/ChangeLog
        PR tree-optimization/98335
        * g++.target/i386/pr98335.C: New test case.


Thanks in advance,
Roger
--

diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index d15170e..f1eb62a 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -4276,6 +4276,26 @@
   [(set_attr "isa" "*,avx512dq,avx512dq")
    (set_attr "type" "imovx,mskmov,mskmov")
    (set_attr "mode" "SI,QI,QI")])
+
+;; Transform xorl; mov[bw] (set strict_low_part) into movz[bw]l.
+(define_peephole2
+  [(parallel [(set (match_operand:DI 0 "general_reg_operand")
+                  (const_int 0))
+             (clobber (reg:CC FLAGS_REG))])
+   (set (strict_low_part (match_operand:SWI12 1 "general_reg_operand"))
+       (match_operand:SWI12 2 "nonimmediate_operand"))]
+  "TARGET_64BIT
+   && REGNO (operands[0]) == REGNO (operands[1])"
+  [(set (match_dup 0) (zero_extend:DI (match_dup 2)))])
+
+;; Likewise, but preserving FLAGS_REG.
+(define_peephole2
+  [(set (match_operand:DI 0 "general_reg_operand") (const_int 0))
+   (set (strict_low_part (match_operand:SWI12 1 "general_reg_operand"))
+       (match_operand:SWI12 2 "nonimmediate_operand"))]
+  "TARGET_64BIT
+   && REGNO (operands[0]) == REGNO (operands[1])"
+  [(set (match_dup 0) (zero_extend:DI (match_dup 2)))])
 
 ;; Sign extension instructions
 
diff --git a/gcc/testsuite/g++.target/i386/pr98335.C 
b/gcc/testsuite/g++.target/i386/pr98335.C
new file mode 100644
index 0000000..2581b83
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/pr98335.C
@@ -0,0 +1,18 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2" } */
+
+struct Data {
+  char a;
+  int b;
+};
+
+char c;
+
+Data val(int idx) {
+  return { c };  // { dg-warning "extended initializer" "c++ 98"  { target { 
c++98_only } } }
+}
+
+/* { dg-final { scan-assembler "movzbl" } } */
+/* { dg-final { scan-assembler-not "xorl" } } */
+/* { dg-final { scan-assembler-not "movb" } } */
+

Reply via email to