From: Oleg Endo Date: Mon, 20 May 2013 16:18:44 +0000 (+0000) Subject: re PR tree-optimization/56547 ([SH] missed opportunity for fmac with -ffast-math) X-Git-Tag: releases/gcc-4.9.0~5801 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=14c2ec26e2d1232b88906927355517d34ffdbab6;p=thirdparty%2Fgcc.git re PR tree-optimization/56547 ([SH] missed opportunity for fmac with -ffast-math) PR target/56547 * config/sh/sh.md (fmasf4): Remove empty constraints strings. (*fmasf4, *fmasf4_media): New insns. PR target/56547 * gcc.target/sh/pr56547-1.c: New. * gcc.target/sh/pr56547-2.c: New. From-SVN: r199110 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 310c14d97fd9..a89b15c6c6bd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2013-05-20 Oleg Endo + + PR target/56547 + * config/sh/sh.md (fmasf4): Remove empty constraints strings. + (*fmasf4, *fmasf4_media): New insns. + 2013-05-19 Richard Sandiford * config/mips/mips.h (BASE_INSN_LENGTH, NOP_INSN_LENGTH): New macros. diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index 71ad1c1a2f67..8a1406876541 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -12251,10 +12251,10 @@ label: ;; FMA (fused multiply-add) patterns (define_expand "fmasf4" - [(set (match_operand:SF 0 "fp_arith_reg_operand" "") - (fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "") - (match_operand:SF 2 "fp_arith_reg_operand" "") - (match_operand:SF 3 "fp_arith_reg_operand" "")))] + [(set (match_operand:SF 0 "fp_arith_reg_operand") + (fma:SF (match_operand:SF 1 "fp_arith_reg_operand") + (match_operand:SF 2 "fp_arith_reg_operand") + (match_operand:SF 3 "fp_arith_reg_operand")))] "TARGET_SH2E || TARGET_SHMEDIA_FPU" { if (TARGET_SH2E) @@ -12285,6 +12285,43 @@ label: "fmac.s %1, %2, %0" [(set_attr "type" "fparith_media")]) +;; For some cases such as 'a * b + a' the FMA pattern is not generated by +;; previous transformations. If FMA is generally allowed, let the combine +;; pass utilize it. +(define_insn_and_split "*fmasf4" + [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") + (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w") + (match_operand:SF 2 "fp_arith_reg_operand" "f")) + (match_operand:SF 3 "arith_reg_operand" "0"))) + (use (match_operand:PSI 4 "fpscr_operand"))] + "TARGET_SH2E && flag_fp_contract_mode != FP_CONTRACT_OFF" + "fmac %1,%2,%0" + "&& can_create_pseudo_p ()" + [(parallel [(set (match_dup 0) + (fma:SF (match_dup 1) (match_dup 2) (match_dup 3))) + (use (match_dup 4))])] +{ + /* Change 'b * a + a' into 'a * b + a'. + This is better for register allocation. */ + if (REGNO (operands[2]) == REGNO (operands[3])) + { + rtx tmp = operands[1]; + operands[1] = operands[2]; + operands[2] = tmp; + } +} + [(set_attr "type" "fp") + (set_attr "fp_mode" "single")]) + +(define_insn "*fmasf4_media" + [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") + (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f") + (match_operand:SF 2 "fp_arith_reg_operand" "f")) + (match_operand:SF 3 "fp_arith_reg_operand" "0")))] + "TARGET_SHMEDIA_FPU && flag_fp_contract_mode != FP_CONTRACT_OFF" + "fmac.s %1, %2, %0" + [(set_attr "type" "fparith_media")]) + (define_expand "divsf3" [(set (match_operand:SF 0 "arith_reg_operand" "") (div:SF (match_operand:SF 1 "arith_reg_operand" "") diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6f7bf4110d83..85aac1e2a103 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2013-05-20 Oleg Endo + + PR target/56547 + * gcc.target/sh/pr56547-1.c: New. + * gcc.target/sh/pr56547-2.c: New. + 2013-05-20 Paolo Carlini PR c++/23608 diff --git a/gcc/testsuite/gcc.target/sh/pr56547-1.c b/gcc/testsuite/gcc.target/sh/pr56547-1.c new file mode 100644 index 000000000000..0ba21a685a4c --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr56547-1.c @@ -0,0 +1,19 @@ +/* Verify that the fmac insn is used for the expression 'a * b + a' and + 'a * a + a'. + This assumes that the default compiler setting is -ffp-contract=fast. */ +/* { dg-do compile { target "sh*-*-*" } } */ +/* { dg-options "-O1" } */ +/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2" "-m3" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */ +/* { dg-final { scan-assembler-times "fmac" 2 } } */ + +float +test_00 (float a, float b) +{ + return a * b + a; +} + +float +test_01 (float a) +{ + return a * a + a; +} diff --git a/gcc/testsuite/gcc.target/sh/pr56547-2.c b/gcc/testsuite/gcc.target/sh/pr56547-2.c new file mode 100644 index 000000000000..02e1a0f86f40 --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr56547-2.c @@ -0,0 +1,18 @@ +/* Verify that the fmac insn is used for the expression 'a * b + a' and + 'a * a + a' when -ffast-math is specified. */ +/* { dg-do compile { target "sh*-*-*" } } */ +/* { dg-options "-O1 -ffast-math" } */ +/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2" "-m3" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */ +/* { dg-final { scan-assembler-times "fmac" 2 } } */ + +float +test_00 (float a, float b) +{ + return a * b + a; +} + +float +test_01 (float a) +{ + return a * a + a; +}