]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
x86: Avoid generating orb $0, %ah
authorRoger Sayle <roger@nextmovesoftware.com>
Mon, 13 Dec 2021 18:48:22 +0000 (18:48 +0000)
committerRoger Sayle <roger@nextmovesoftware.com>
Mon, 13 Dec 2021 18:51:00 +0000 (18:51 +0000)
I'll post my proposed fix for PR target/103611 shortly, but this patch
fixes another missed optimization opportunity revealed by that PR.
Occasionally, reload materializes integer constants during register
allocation sometimes resulting in unnecessary instructions such as:

(insn 23 31 24 2 (parallel [
            (set (reg:SI 0 ax [99])
                (ior:SI (reg:SI 0 ax [99])
                    (const_int 0 [0])))
            (clobber (reg:CC 17 flags))
        ]) "pr103611.c":18:73 550 {*iorsi_1}
     (nil))

These then get "optimized" during the split2 pass, which realizes that
no bits outside of 0xff00 are set, so this operation can be implemented
by operating on just the highpart of a QIreg_operand, i.e. %ah, %bh, %ch
etc., which leads to the useless "orb $0, %ah" seen in the reported PR.

This fix catches the case of const0_rtx in relevant splitter, either
eliminating the instruction or turning it into a simple move.

2021-12-13  Roger Sayle  <roger@nextmovesoftware.com>

gcc/ChangeLog
* config/i386/i386.md (define_split any_or:SWI248 -> orb %?h):
Optimize the case where the integer constant operand is zero.

gcc/testsuite/ChangeLog
* gcc.target/i386/pr103611-1.c: New test case.

gcc/config/i386/i386.md
gcc/testsuite/gcc.target/i386/pr103611-1.c [new file with mode: 0644]

index 9d7d1161d15ed8fb73bf6f32c0a3134d5b8a9cb4..f6d9c4ba6cc9872dfa5b46466711572ec04293de 100644 (file)
               (match_dup 2)) 0))
       (clobber (reg:CC FLAGS_REG))])]
 {
+  /* Handle the case where INTVAL (operands[2]) == 0.  */
+  if (operands[2] == const0_rtx)
+    {
+      if (!rtx_equal_p (operands[0], operands[1]))
+       emit_move_insn (operands[0], operands[1]);
+      else
+       emit_note (NOTE_INSN_DELETED);
+      DONE;
+    }
   operands[0] = gen_lowpart (SImode, operands[0]);
   operands[1] = gen_lowpart (SImode, operands[1]);
   operands[2] = gen_int_mode (INTVAL (operands[2]) >> 8, QImode);
diff --git a/gcc/testsuite/gcc.target/i386/pr103611-1.c b/gcc/testsuite/gcc.target/i386/pr103611-1.c
new file mode 100644 (file)
index 0000000..7d8ac9d
--- /dev/null
@@ -0,0 +1,30 @@
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O2 -msse4" } */
+typedef int __v4si __attribute__ ((__vector_size__ (16)));
+
+long long ior_1(__v4si v) {
+  unsigned int loVal = (unsigned int)v[0];
+  unsigned int hiVal = (unsigned int)v[1];
+  return (long long)(loVal) | ((long long)(hiVal) << 32);
+}
+
+long long ior_2(__v4si v) {
+  unsigned int loVal = (unsigned int)v[2];
+  unsigned int hiVal = (unsigned int)v[3];
+  return (long long)(loVal) | ((long long)(hiVal) << 32);
+}
+
+long long xor_1(__v4si v) {
+  unsigned int loVal = (unsigned int)v[0];
+  unsigned int hiVal = (unsigned int)v[1];
+  return (long long)(loVal) ^ ((long long)(hiVal) << 32);
+}
+
+long long xor_2(__v4si v) {
+  unsigned int loVal = (unsigned int)v[2];
+  unsigned int hiVal = (unsigned int)v[3];
+  return (long long)(loVal) ^ ((long long)(hiVal) << 32);
+}
+/* { dg-final { scan-assembler-not "\torb\t\\\$0," } } */
+/* { dg-final { scan-assembler-not "\txorb\t\\\$0," } } */
+