diff options
author | Roger Sayle <roger@nextmovesoftware.com> | 2023-07-20 09:23:11 +0100 |
---|---|---|
committer | Roger Sayle <roger@nextmovesoftware.com> | 2023-07-20 09:24:50 +0100 |
commit | 097106972f243ddcbddbbddd9a6bcc076f58b453 (patch) | |
tree | fa6c8a772e3f0aa50c5181fc78d3e3d1bcda6f87 /gcc | |
parent | ceae1400cf24f329393e96dd9720b0391afe858d (diff) | |
download | gcc-097106972f243ddcbddbbddd9a6bcc076f58b453.zip gcc-097106972f243ddcbddbbddd9a6bcc076f58b453.tar.gz gcc-097106972f243ddcbddbbddd9a6bcc076f58b453.tar.bz2 |
i386: More TImode parameter passing improvements.
This patch is the next piece of a solution to the x86_64 ABI issues in
PR 88873. This splits the *concat<mode><dwi>3_3 define_insn_and_split
into two patterns, a TARGET_64BIT *concatditi3_3 and a !TARGET_64BIT
*concatsidi3_3. This allows us to add an additional alternative to the
the 64-bit version, enabling the register allocator to perform this
operation using SSE registers, which is implemented/split after reload
using vec_concatv2di.
To demonstrate the improvement, the test case from PR88873:
typedef struct { double x, y; } s_t;
s_t foo (s_t a, s_t b, s_t c)
{
return (s_t){ __builtin_fma(a.x, b.x, c.x), __builtin_fma (a.y, b.y, c.y) };
}
when compiled with -O2 -march=cascadelake, currently generates:
foo: vmovq %xmm2, -56(%rsp)
movq -56(%rsp), %rax
vmovq %xmm3, -48(%rsp)
vmovq %xmm4, -40(%rsp)
movq -48(%rsp), %rcx
vmovq %xmm5, -32(%rsp)
vmovq %rax, %xmm6
movq -40(%rsp), %rax
movq -32(%rsp), %rsi
vpinsrq $1, %rcx, %xmm6, %xmm6
vmovq %xmm0, -24(%rsp)
vmovq %rax, %xmm7
vmovq %xmm1, -16(%rsp)
vmovapd %xmm6, %xmm2
vpinsrq $1, %rsi, %xmm7, %xmm7
vfmadd132pd -24(%rsp), %xmm7, %xmm2
vmovapd %xmm2, -56(%rsp)
vmovsd -48(%rsp), %xmm1
vmovsd -56(%rsp), %xmm0
ret
with this change, we avoid many of the reloads via memory,
foo: vpunpcklqdq %xmm3, %xmm2, %xmm7
vpunpcklqdq %xmm1, %xmm0, %xmm6
vpunpcklqdq %xmm5, %xmm4, %xmm2
vmovdqa %xmm7, -24(%rsp)
vmovdqa %xmm6, %xmm1
movq -16(%rsp), %rax
vpinsrq $1, %rax, %xmm7, %xmm4
vmovapd %xmm4, %xmm6
vfmadd132pd %xmm1, %xmm2, %xmm6
vmovapd %xmm6, -24(%rsp)
vmovsd -16(%rsp), %xmm1
vmovsd -24(%rsp), %xmm0
ret
2023-07-20 Roger Sayle <roger@nextmovesoftware.com>
gcc/ChangeLog
* config/i386/i386-expand.cc (ix86_expand_move): Don't call
force_reg, to use SUBREG rather than create a new pseudo when
inserting DFmode fields into TImode with insvti_{high,low}part.
* config/i386/i386.md (*concat<mode><dwi>3_3): Split into two
define_insn_and_split...
(*concatditi3_3): 64-bit implementation. Provide alternative
that allows register allocation to use SSE registers that is
split into vec_concatv2di after reload.
(*concatsidi3_3): 32-bit implementation.
gcc/testsuite/ChangeLog
* gcc.target/i386/pr88873.c: New test case.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/i386/i386-expand.cc | 4 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 46 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr88873.c | 11 |
3 files changed, 49 insertions, 12 deletions
diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc index a82c2bd..a5c000f 100644 --- a/gcc/config/i386/i386-expand.cc +++ b/gcc/config/i386/i386-expand.cc @@ -558,7 +558,7 @@ ix86_expand_move (machine_mode mode, rtx operands[]) op0 = SUBREG_REG (op0); tmp = gen_rtx_AND (TImode, copy_rtx (op0), tmp); if (mode == DFmode) - op1 = force_reg (DImode, gen_lowpart (DImode, op1)); + op1 = gen_lowpart (DImode, op1); op1 = gen_rtx_ZERO_EXTEND (TImode, op1); op1 = gen_rtx_IOR (TImode, tmp, op1); } @@ -570,7 +570,7 @@ ix86_expand_move (machine_mode mode, rtx operands[]) op0 = SUBREG_REG (op0); tmp = gen_rtx_AND (TImode, copy_rtx (op0), tmp); if (mode == DFmode) - op1 = force_reg (DImode, gen_lowpart (DImode, op1)); + op1 = gen_lowpart (DImode, op1); op1 = gen_rtx_ZERO_EXTEND (TImode, op1); op1 = gen_rtx_ASHIFT (TImode, op1, GEN_INT (64)); op1 = gen_rtx_IOR (TImode, tmp, op1); diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 47ea050..8c54aa5 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -12408,21 +12408,47 @@ DONE; }) -(define_insn_and_split "*concat<mode><dwi>3_3" - [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,r,&r") - (any_or_plus:<DWI> - (ashift:<DWI> - (zero_extend:<DWI> - (match_operand:DWIH 1 "nonimmediate_operand" "r,m,r,m")) +(define_insn_and_split "*concatditi3_3" + [(set (match_operand:TI 0 "nonimmediate_operand" "=ro,r,r,&r,x") + (any_or_plus:TI + (ashift:TI + (zero_extend:TI + (match_operand:DI 1 "nonimmediate_operand" "r,m,r,m,x")) (match_operand:QI 2 "const_int_operand")) - (zero_extend:<DWI> - (match_operand:DWIH 3 "nonimmediate_operand" "r,r,m,m"))))] - "INTVAL (operands[2]) == <MODE_SIZE> * BITS_PER_UNIT" + (zero_extend:TI + (match_operand:DI 3 "nonimmediate_operand" "r,r,m,m,0"))))] + "TARGET_64BIT + && INTVAL (operands[2]) == 64" + "#" + "&& reload_completed" + [(const_int 0)] +{ + if (SSE_REG_P (operands[0])) + { + rtx tmp = gen_rtx_REG (V2DImode, REGNO (operands[0])); + emit_insn (gen_vec_concatv2di (tmp, operands[3], operands[1])); + } + else + split_double_concat (TImode, operands[0], operands[3], operands[1]); + DONE; +}) + +(define_insn_and_split "*concatsidi3_3" + [(set (match_operand:DI 0 "nonimmediate_operand" "=ro,r,r,&r") + (any_or_plus:DI + (ashift:DI + (zero_extend:DI + (match_operand:SI 1 "nonimmediate_operand" "r,m,r,m")) + (match_operand:QI 2 "const_int_operand")) + (zero_extend:DI + (match_operand:SI 3 "nonimmediate_operand" "r,r,m,m"))))] + "!TARGET_64BIT + && INTVAL (operands[2]) == 32" "#" "&& reload_completed" [(const_int 0)] { - split_double_concat (<DWI>mode, operands[0], operands[3], operands[1]); + split_double_concat (DImode, operands[0], operands[3], operands[1]); DONE; }) diff --git a/gcc/testsuite/gcc.target/i386/pr88873.c b/gcc/testsuite/gcc.target/i386/pr88873.c new file mode 100644 index 0000000..d893aac --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr88873.c @@ -0,0 +1,11 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O2 -march=cascadelake" } */ + +typedef struct { double x, y; } s_t; + +s_t foo (s_t a, s_t b, s_t c) +{ + return (s_t) { __builtin_fma(a.x, b.x, c.x), __builtin_fma (a.y, b.y, c.y) }; +} + +/* { dg-final { scan-assembler-times "vpunpcklqdq" 3 } } */ |