]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
i386: Improve access to _Atomic DImode location via XMM regs for SSE4.1 x86_32 targets
authorUros Bizjak <ubizjak@gmail.com>
Tue, 28 May 2024 18:25:14 +0000 (20:25 +0200)
committerUros Bizjak <ubizjak@gmail.com>
Tue, 28 May 2024 20:59:12 +0000 (22:59 +0200)
Use MOVD/PEXTRD and MOVD/PINSRD insn sequences to move DImode value
between XMM and GPR register sets for SSE4.1 x86_32 targets in order
to avoid spilling the value to stack.

The load from _Atomic location a improves from:

movq    a, %xmm0
movq    %xmm0, (%esp)
movl    (%esp), %eax
movl    4(%esp), %edx

to:
movq    a, %xmm0
movd    %xmm0, %eax
pextrd  $1, %xmm0, %edx

The store to _Atomic location b improves from:

movl    %eax, (%esp)
movl    %edx, 4(%esp)
movq    (%esp), %xmm0
movq    %xmm0, b

to:
movd    %eax, %xmm0
pinsrd  $1, %edx, %xmm0
movq    %xmm0, b

gcc/ChangeLog:

* config/i386/sync.md (atomic_loaddi_fpu): Use movd/pextrd
to move DImode value from XMM to GPR for TARGET_SSE4_1.
(atomic_storedi_fpu): Use movd/pinsrd to move DImode value
from GPR to XMM for TARGET_SSE4_1.

gcc/config/i386/sync.md

index 8317581ebe27861f1e1bc8671ba617b1ea230347..f2b3ba0aa7aa8df2d064a8c831701b67633df5fd 100644 (file)
        }
       else
        {
+         rtx tmpdi = gen_lowpart (DImode, tmp);
+
          emit_insn (gen_loaddi_via_sse (tmp, src));
-         emit_insn (gen_storedi_via_sse (mem, tmp));
+
+         if (GENERAL_REG_P (dst)
+             && TARGET_SSE4_1 && TARGET_INTER_UNIT_MOVES_FROM_VEC)
+           {
+             emit_move_insn (dst, tmpdi);
+             DONE;
+           }
+         else
+           emit_move_insn (mem, tmpdi);
        }
 
       if (mem != dst)
     emit_move_insn (dst, src);
   else
     {
-      if (REG_P (src))
-       {
-         emit_move_insn (mem, src);
-         src = mem;
-       }
-
       if (STACK_REG_P (tmp))
        {
+         if (GENERAL_REG_P (src))
+           {
+             emit_move_insn (mem, src);
+             src = mem;
+           }
+
          emit_insn (gen_loaddi_via_fpu (tmp, src));
          emit_insn (gen_storedi_via_fpu (dst, tmp));
        }
       else
        {
-         emit_insn (gen_loaddi_via_sse (tmp, src));
+         rtx tmpdi = gen_lowpart (DImode, tmp);
+
+         if (GENERAL_REG_P (src)
+             && !(TARGET_SSE4_1 && TARGET_INTER_UNIT_MOVES_TO_VEC))
+           {
+             emit_move_insn (mem, src);
+             src = mem;
+           }
+
+         emit_move_insn (tmpdi, src);
+
          emit_insn (gen_storedi_via_sse (dst, tmp));
        }
     }