rs6000: Add expand pattern for multiply-add (PR103109)
gcc/ PR target/103109 * config/rs6000/rs6000.md (<u>maddditi4): New pattern for multiply-add. (<u>madddi4_highpart): New. (<u>madddi4_highpart_le): New. gcc/testsuite/ PR target/103109 * gcc.target/powerpc/pr103109.h: New. * gcc.target/powerpc/pr103109-1.c: New. * gcc.target/powerpc/pr103109-2.c: New.
This commit is contained in:
parent
4645ce0d00
commit
defa08a336
4 changed files with 165 additions and 1 deletions
|
@ -3217,7 +3217,7 @@
|
|||
DONE;
|
||||
})
|
||||
|
||||
(define_insn "*maddld<mode>4"
|
||||
(define_insn "maddld<mode>4"
|
||||
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
|
||||
(plus:GPR (mult:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
|
||||
(match_operand:GPR 2 "gpc_reg_operand" "r"))
|
||||
|
@ -3226,6 +3226,52 @@
|
|||
"maddld %0,%1,%2,%3"
|
||||
[(set_attr "type" "mul")])
|
||||
|
||||
(define_expand "<u>maddditi4"
|
||||
[(set (match_operand:TI 0 "gpc_reg_operand")
|
||||
(plus:TI
|
||||
(mult:TI (any_extend:TI (match_operand:DI 1 "gpc_reg_operand"))
|
||||
(any_extend:TI (match_operand:DI 2 "gpc_reg_operand")))
|
||||
(any_extend:TI (match_operand:DI 3 "gpc_reg_operand"))))]
|
||||
"TARGET_MADDLD && TARGET_POWERPC64"
|
||||
{
|
||||
rtx op0_lo = gen_rtx_SUBREG (DImode, operands[0], BYTES_BIG_ENDIAN ? 8 : 0);
|
||||
rtx op0_hi = gen_rtx_SUBREG (DImode, operands[0], BYTES_BIG_ENDIAN ? 0 : 8);
|
||||
|
||||
emit_insn (gen_maddlddi4 (op0_lo, operands[1], operands[2], operands[3]));
|
||||
|
||||
if (BYTES_BIG_ENDIAN)
|
||||
emit_insn (gen_<u>madddi4_highpart (op0_hi, operands[1], operands[2],
|
||||
operands[3]));
|
||||
else
|
||||
emit_insn (gen_<u>madddi4_highpart_le (op0_hi, operands[1], operands[2],
|
||||
operands[3]));
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_insn "<u>madddi4_highpart"
|
||||
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
|
||||
(subreg:DI
|
||||
(plus:TI
|
||||
(mult:TI (any_extend:TI (match_operand:DI 1 "gpc_reg_operand" "r"))
|
||||
(any_extend:TI (match_operand:DI 2 "gpc_reg_operand" "r")))
|
||||
(any_extend:TI (match_operand:DI 3 "gpc_reg_operand" "r")))
|
||||
0))]
|
||||
"TARGET_MADDLD && BYTES_BIG_ENDIAN && TARGET_POWERPC64"
|
||||
"maddhd<u> %0,%1,%2,%3"
|
||||
[(set_attr "type" "mul")])
|
||||
|
||||
(define_insn "<u>madddi4_highpart_le"
|
||||
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
|
||||
(subreg:DI
|
||||
(plus:TI
|
||||
(mult:TI (any_extend:TI (match_operand:DI 1 "gpc_reg_operand" "r"))
|
||||
(any_extend:TI (match_operand:DI 2 "gpc_reg_operand" "r")))
|
||||
(any_extend:TI (match_operand:DI 3 "gpc_reg_operand" "r")))
|
||||
8))]
|
||||
"TARGET_MADDLD && !BYTES_BIG_ENDIAN && TARGET_POWERPC64"
|
||||
"maddhd<u> %0,%1,%2,%3"
|
||||
[(set_attr "type" "mul")])
|
||||
|
||||
(define_insn "udiv<mode>3"
|
||||
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
|
||||
(udiv:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
|
||||
|
|
10
gcc/testsuite/gcc.target/powerpc/pr103109-1.c
Normal file
10
gcc/testsuite/gcc.target/powerpc/pr103109-1.c
Normal file
|
@ -0,0 +1,10 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -mdejagnu-cpu=power9" } */
|
||||
/* { dg-require-effective-target int128 } */
|
||||
/* { dg-require-effective-target powerpc_p9modulo_ok } */
|
||||
/* { dg-require-effective-target has_arch_ppc64 } */
|
||||
/* { dg-final { scan-assembler-times {\mmaddld\M} 2 } } */
|
||||
/* { dg-final { scan-assembler-times {\mmaddhd\M} 1 } } */
|
||||
/* { dg-final { scan-assembler-times {\mmaddhdu\M} 1 } } */
|
||||
|
||||
#include "pr103109.h"
|
96
gcc/testsuite/gcc.target/powerpc/pr103109-2.c
Normal file
96
gcc/testsuite/gcc.target/powerpc/pr103109-2.c
Normal file
|
@ -0,0 +1,96 @@
|
|||
/* { dg-do run } */
|
||||
/* { dg-options "-O2 -mdejagnu-cpu=power9" } */
|
||||
/* { dg-require-effective-target int128 } */
|
||||
/* { dg-require-effective-target p9modulo_hw } */
|
||||
/* { dg-require-effective-target has_arch_ppc64 } */
|
||||
|
||||
#include "pr103109.h"
|
||||
|
||||
union U {
|
||||
__int128 i128;
|
||||
struct {
|
||||
long l1;
|
||||
long l2;
|
||||
} s;
|
||||
};
|
||||
|
||||
__int128
|
||||
create_i128 (long most_sig, long least_sig)
|
||||
{
|
||||
union U u;
|
||||
|
||||
#if __LITTLE_ENDIAN__
|
||||
u.s.l1 = least_sig;
|
||||
u.s.l2 = most_sig;
|
||||
#else
|
||||
u.s.l1 = most_sig;
|
||||
u.s.l2 = least_sig;
|
||||
#endif
|
||||
return u.i128;
|
||||
}
|
||||
|
||||
#define DEBUG 0
|
||||
|
||||
#if DEBUG
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void print_i128(__int128 val, int unsignedp)
|
||||
{
|
||||
if (unsignedp)
|
||||
printf(" %llu ", (unsigned long long)(val >> 64));
|
||||
else
|
||||
printf(" %lld ", (signed long long)(val >> 64));
|
||||
|
||||
printf("%llu (0x%llx %llx)",
|
||||
(unsigned long long)(val & 0xFFFFFFFFFFFFFFFF),
|
||||
(unsigned long long)(val >> 64),
|
||||
(unsigned long long)(val & 0xFFFFFFFFFFFFFFFF));
|
||||
}
|
||||
#endif
|
||||
|
||||
void abort (void);
|
||||
|
||||
int main ()
|
||||
{
|
||||
long a = 0xFEDCBA9876543210L;
|
||||
long b = 0x1000000L;
|
||||
long c = 0x123456L;
|
||||
__int128 expected_result = create_i128 (0xFFFFFFFFFFFEDCBAL,
|
||||
0x9876543210123456L);
|
||||
|
||||
__int128 result = multiply_add (a, b, c);
|
||||
|
||||
if (result != expected_result)
|
||||
{
|
||||
#if DEBUG
|
||||
printf ("ERROR: multiply_add (%lld, %lld, %lld) = ", a, b, c);
|
||||
print_i128 (result, 0);
|
||||
printf ("\n does not match expected_result = ");
|
||||
print_i128 (expected_result, 0);
|
||||
printf ("\n\n");
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned long au = 0xFEDCBA9876543210UL;
|
||||
unsigned long bu = 0x1000000UL;
|
||||
unsigned long cu = 0x123456UL;
|
||||
unsigned __int128 expected_resultu = create_i128 (0x0000000000FEDCBAL,
|
||||
0x9876543210123456L);
|
||||
|
||||
unsigned __int128 resultu = multiply_addu (au, bu, cu);
|
||||
if (resultu != expected_resultu)
|
||||
{
|
||||
#if DEBUG
|
||||
printf ("ERROR: multiply_addu (%llu, %llu, %llu) = ", au, bu, cu);
|
||||
print_i128 (resultu, 1);
|
||||
printf ("\n does not match expected_result = ");
|
||||
print_i128 (expected_resultu, 1);
|
||||
printf ("\n\n");
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
}
|
12
gcc/testsuite/gcc.target/powerpc/pr103109.h
Normal file
12
gcc/testsuite/gcc.target/powerpc/pr103109.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
__attribute__((noinline))
|
||||
__int128 multiply_add (long a, long b, long c)
|
||||
{
|
||||
return (__int128) a * b + c;
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
unsigned __int128 multiply_addu (unsigned long a, unsigned long b,
|
||||
unsigned long c)
|
||||
{
|
||||
return (unsigned __int128) a * b + c;
|
||||
}
|
Loading…
Add table
Reference in a new issue