2
0
mirror of git://gcc.gnu.org/git/gcc.git synced 2025-03-23 14:11:05 +08:00

i386: Add *concat<mode><dwi>3_{5,6,7} patterns [PR107627]

On Thu, Dec 01, 2022 at 09:09:51AM +0100, Jakub Jelinek via Gcc-patches wrote:
> BTW, I wonder if we couldn't add additional patterns which would catch
> the case where one of the operands is constant.

The following patch does add those.
The difference with the patch on the 2 testcases is:
 baz:
-       movq    8(%rsi), %rax
+       movq    8(%rsi), %rsi
+       movq    %rdi, %r8
        movl    %edx, %ecx
-       xorl    %r8d, %r8d
-       xorl    %edx, %edx
-       movabsq $-2401053089206453570, %r9
-       orq     %r8, %rax
-       orq     %r9, %rdx
-       shrdq   %rdx, %rax
-       movq    %rax, (%rdi)
+       movabsq $-2401053089206453570, %rdi
+       movq    %rsi, %rax
+       shrdq   %rdi, %rax
+       movq    %rax, (%r8)
 qux:
-       movq    (%rsi), %rax
+       movq    %rdi, %r8
+       movq    (%rsi), %rdi
        movl    %edx, %ecx
-       xorl    %r9d, %r9d
-       movabsq $-2401053089206453570, %r8
-       movq    %rax, %rdx
-       xorl    %eax, %eax
-       orq     %r8, %rax
-       orq     %r9, %rdx
-       shrdq   %rdx, %rax
-       movq    %rax, (%rdi)
+       movabsq $-2401053089206453570, %rsi
+       movq    %rsi, %rax
+       shrdq   %rdi, %rax
+       movq    %rax, (%r8)
and
 garply:
        pushl   %esi
-       xorl    %edx, %edx
+       movl    $-559038737, %esi
        pushl   %ebx
        movl    16(%esp), %eax
-       orl     $-559038737, %edx
        movl    20(%esp), %ecx
-       movl    4(%eax), %eax
-       shrdl   %edx, %eax
        movl    12(%esp), %edx
+       movl    4(%eax), %ebx
+       movl    %ebx, %eax
+       shrdl   %esi, %eax
 fred:
...
        movl    16(%esp), %eax
+       movl    $-889275714, %ebx
        movl    20(%esp), %ecx
-       movl    (%eax), %eax
-       movl    %eax, %edx
-       movl    $0, %eax
-       orl     $-889275714, %eax
-       shrdl   %edx, %eax
        movl    12(%esp), %edx
+       movl    (%eax), %esi
+       movl    %ebx, %eax
+       shrdl   %esi, %eax

2022-12-08  Jakub Jelinek  <jakub@redhat.com>

	PR target/107627
	* config/i386/i386.md (HALF, half): New mode attributes.
	(*concat<half><mode>3_5, *concat<mode><dwi>3_6,
	*concat<mode><dwi>3_7): New define_insn_and_split patterns.

	* gcc.target/i386/pr107627-3.c: New test.
	* gcc.target/i386/pr107627-4.c: New test.
This commit is contained in:
Jakub Jelinek 2022-12-08 14:55:46 +01:00
parent 0ef9991d87
commit 1dc49df4ee
3 changed files with 134 additions and 0 deletions
gcc
config/i386
testsuite/gcc.target/i386

@ -1134,6 +1134,10 @@
(define_mode_attr DWI [(QI "HI") (HI "SI") (SI "DI") (DI "TI") (TI "OI")])
(define_mode_attr dwi [(QI "hi") (HI "si") (SI "di") (DI "ti") (TI "oi")])
;; Half sized integer modes.
(define_mode_attr HALF [(TI "DI") (DI "SI")])
(define_mode_attr half [(TI "di") (DI "si")])
;; LEA mode corresponding to an integer mode
(define_mode_attr LEAMODE [(QI "SI") (HI "SI") (SI "SI") (DI "DI")])
@ -11464,6 +11468,80 @@
split_double_concat (<DWI>mode, operands[0], operands[1], operands[2]);
DONE;
})
(define_insn_and_split "*concat<half><mode>3_5"
[(set (match_operand:DWI 0 "nonimmediate_operand" "=ro")
(any_or_plus:DWI
(ashift:DWI (match_operand:DWI 1 "register_operand" "r")
(match_operand:DWI 2 "const_int_operand"))
(match_operand:DWI 3 "const_scalar_int_operand")))]
"INTVAL (operands[2]) == <MODE_SIZE> * BITS_PER_UNIT / 2
&& (<MODE>mode == DImode
? CONST_INT_P (operands[3])
&& (UINTVAL (operands[3]) & ~GET_MODE_MASK (SImode)) == 0
: CONST_INT_P (operands[3])
? INTVAL (operands[3]) >= 0
: CONST_WIDE_INT_NUNITS (operands[3]) == 2
&& CONST_WIDE_INT_ELT (operands[3], 1) == 0)"
"#"
"&& reload_completed"
[(clobber (const_int 0))]
{
rtx op3 = simplify_subreg (<HALF>mode, operands[3], <MODE>mode, 0);
split_double_concat (<MODE>mode, operands[0], op3,
gen_lowpart (<HALF>mode, operands[1]));
DONE;
})
(define_insn_and_split "*concat<mode><dwi>3_6"
[(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r")
(any_or_plus:<DWI>
(ashift:<DWI>
(zero_extend:<DWI>
(match_operand:DWIH 1 "nonimmediate_operand" "r,m"))
(match_operand:<DWI> 2 "const_int_operand"))
(match_operand:<DWI> 3 "const_scalar_int_operand")))]
"INTVAL (operands[2]) == <MODE_SIZE> * BITS_PER_UNIT
&& (<DWI>mode == DImode
? CONST_INT_P (operands[3])
&& (UINTVAL (operands[3]) & ~GET_MODE_MASK (SImode)) == 0
: CONST_INT_P (operands[3])
? INTVAL (operands[3]) >= 0
: CONST_WIDE_INT_NUNITS (operands[3]) == 2
&& CONST_WIDE_INT_ELT (operands[3], 1) == 0)"
"#"
"&& reload_completed"
[(clobber (const_int 0))]
{
rtx op3 = simplify_subreg (<MODE>mode, operands[3], <DWI>mode, 0);
split_double_concat (<DWI>mode, operands[0], op3, operands[1]);
DONE;
})
(define_insn_and_split "*concat<mode><dwi>3_7"
[(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r")
(any_or_plus:<DWI>
(zero_extend:<DWI>
(match_operand:DWIH 1 "nonimmediate_operand" "r,m"))
(match_operand:<DWI> 2 "const_scalar_int_operand")))]
"<DWI>mode == DImode
? CONST_INT_P (operands[2])
&& (UINTVAL (operands[2]) & GET_MODE_MASK (SImode)) == 0
: CONST_WIDE_INT_P (operands[2])
&& CONST_WIDE_INT_NUNITS (operands[2]) == 2
&& CONST_WIDE_INT_ELT (operands[2], 0) == 0"
"#"
"&& reload_completed"
[(clobber (const_int 0))]
{
rtx op2;
if (<DWI>mode == DImode)
op2 = gen_int_mode (INTVAL (operands[2]) >> 32, <MODE>mode);
else
op2 = gen_int_mode (CONST_WIDE_INT_ELT (operands[2], 1), <MODE>mode);
split_double_concat (<DWI>mode, operands[0], operands[1], op2);
DONE;
})
;; Negation instructions

@ -0,0 +1,28 @@
/* PR target/107627 */
/* { dg-do compile { target int128 } } */
/* { dg-options "-O2 -masm=att" } */
/* { dg-final { scan-assembler-not "\torq\t" } } */
static inline unsigned __int128
foo (unsigned long long x, unsigned long long y)
{
return ((unsigned __int128) x << 64) | y;
}
static inline unsigned long long
bar (unsigned long long x, unsigned long long y, unsigned z)
{
return foo (x, y) >> (z % 64);
}
void
baz (unsigned long long *x, const unsigned long long *y, unsigned z)
{
x[0] = bar (0xdeadbeefcafebabeULL, y[1], z);
}
void
qux (unsigned long long *x, const unsigned long long *y, unsigned z)
{
x[0] = bar (y[0], 0xdeadbeefcafebabeULL, z);
}

@ -0,0 +1,28 @@
/* PR target/107627 */
/* { dg-do compile { target ia32 } } */
/* { dg-options "-O2 -masm=att" } */
/* { dg-final { scan-assembler-not "\torl\t" } } */
static inline unsigned long long
qux (unsigned int x, unsigned int y)
{
return ((unsigned long long) x << 32) | y;
}
static inline unsigned int
corge (unsigned int x, unsigned int y, unsigned z)
{
return qux (x, y) >> (z % 32);
}
void
garply (unsigned int *x, const unsigned int *y, unsigned z)
{
x[0] = corge (0xdeadbeefU, y[1], z);
}
void
fred (unsigned int *x, const unsigned int *y, unsigned z)
{
x[0] = corge (y[0], 0xcafebabeU, z);
}