re PR target/54680 ([SH] Unnecessary int-float-int conversion of fsca fixed point input)

PR target/54680
	* config/sh/sh.c (sh_fsca_sf2int, sh_fsca_int2sf): Fix swapped
	comments.
	* config/sh/predicates.md (fpul_operand): Add comment.
	(fpul_fsca_operand, fsca_scale_factor): New predicates.
	* config/sh/sh.md (fsca): Move below sincossf3 expander.  Convert to
	insn_and_split.  Use fpul_fsca_operand and fsca_scale_factor predicates.
	Simplify fpul operand in splitter.

	PR target/54680
	* gcc.target/sh/pr54680.c: New.

From-SVN: r192416
This commit is contained in:
Oleg Endo 2012-10-12 23:19:27 +00:00
parent 535269f4f9
commit db292b0ecd
6 changed files with 148 additions and 28 deletions

View File

@ -1,3 +1,14 @@
2012-10-12 Oleg Endo <olegendo@gcc.gnu.org>
PR target/54680
* config/sh/sh.c (sh_fsca_sf2int, sh_fsca_int2sf): Fix swapped
comments.
* config/sh/predicates.md (fpul_operand): Add comment.
(fpul_fsca_operand, fsca_scale_factor): New predicates.
* config/sh/sh.md (fsca): Move below sincossf3 expander. Convert to
insn_and_split. Use fpul_fsca_operand and fsca_scale_factor predicates.
Simplify fpul operand in splitter.
2012-10-12 Jan Hubicka <jh@suse.cz>
* tree-ssa-threadupdate.c (def_split_header_continue_p): Do not

View File

@ -345,8 +345,10 @@
&& GET_MODE (op) == PSImode);
})
;; TODO: Add a comment here.
;; Returns true if OP is an operand that is either the fpul hard reg or
;; a pseudo. This prevents combine from propagating function arguments
;; in hard regs into insns that need the operand in fpul. If it's a pseudo
;; reload can fix it up.
(define_predicate "fpul_operand"
(match_code "reg")
{
@ -358,6 +360,29 @@
&& GET_MODE (op) == mode);
})
;; Returns true if OP is a valid fpul input operand for the fsca insn.
;; The value in fpul is a fixed-point value and its scaling is described
;; in the fsca insn by a mult:SF. To allow pre-scaled fixed-point inputs
;; in fpul we have to permit things like
;; (reg:SI)
;; (fix:SF (float:SF (reg:SI)))
(define_predicate "fpul_fsca_operand"
(match_code "fix,reg")
{
if (fpul_operand (op, SImode))
return true;
if (GET_CODE (op) == FIX && GET_MODE (op) == SImode
&& GET_CODE (XEXP (op, 0)) == FLOAT && GET_MODE (XEXP (op, 0)) == SFmode)
return fpul_fsca_operand (XEXP (XEXP (op, 0), 0),
GET_MODE (XEXP (XEXP (op, 0), 0)));
return false;
})
;; Returns true if OP is a valid constant scale factor for the fsca insn.
(define_predicate "fsca_scale_factor"
(and (match_code "const_double")
(match_test "op == sh_fsca_int2sf ()")))
;; TODO: Add a comment here.
(define_predicate "general_extend_operand"

View File

@ -12659,11 +12659,9 @@ check_use_sfunc_addr (rtx insn, rtx reg)
gcc_unreachable ();
}
/* This function returns a constant rtx that represents pi / 2**15 in
SFmode. it's used to scale SFmode angles, in radians, to a
fixed-point signed 16.16-bit fraction of a full circle, i.e., 2*pi
maps to 0x10000). */
/* This function returns a constant rtx that represents 2**15 / pi in
SFmode. It's used to scale a fixed-point signed 16.16-bit fraction
of a full circle back to an SFmode value, i.e. 0x10000 maps to 2*pi. */
static GTY(()) rtx sh_fsca_sf2int_rtx;
rtx
@ -12680,11 +12678,10 @@ sh_fsca_sf2int (void)
return sh_fsca_sf2int_rtx;
}
/* This function returns a constant rtx that represents 2**15 / pi in
SFmode. it's used to scale a fixed-point signed 16.16-bit fraction
of a full circle back to a SFmode value, i.e., 0x10000 maps to
2*pi). */
/* This function returns a constant rtx that represents pi / 2**15 in
SFmode. It's used to scale SFmode angles, in radians, to a
fixed-point signed 16.16-bit fraction of a full circle, i.e. 2*pi
maps to 0x10000. */
static GTY(()) rtx sh_fsca_int2sf_rtx;
rtx

View File

@ -12208,22 +12208,6 @@ label:
[(set_attr "type" "fsrra")
(set_attr "fp_mode" "single")])
(define_insn "fsca"
[(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
(vec_concat:V2SF
(unspec:SF [(mult:SF
(float:SF (match_operand:SI 1 "fpul_operand" "y"))
(match_operand:SF 2 "immediate_operand" "i"))
] UNSPEC_FSINA)
(unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2))
] UNSPEC_FCOSA)))
(use (match_operand:PSI 3 "fpscr_operand" "c"))]
"TARGET_FPU_ANY && TARGET_FSCA
&& operands[2] == sh_fsca_int2sf ()"
"fsca fpul,%d0"
[(set_attr "type" "fsca")
(set_attr "fp_mode" "single")])
;; When the sincos pattern is defined, the builtin functions sin and cos
;; will be expanded to the sincos pattern and one of the output values will
;; remain unused.
@ -12250,6 +12234,38 @@ label:
DONE;
})
(define_insn_and_split "fsca"
[(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
(vec_concat:V2SF
(unspec:SF [(mult:SF
(float:SF (match_operand:SI 1 "fpul_fsca_operand" "y"))
(match_operand:SF 2 "fsca_scale_factor" "i"))
] UNSPEC_FSINA)
(unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2))
] UNSPEC_FCOSA)))
(use (match_operand:PSI 3 "fpscr_operand" "c"))]
"TARGET_FPU_ANY && TARGET_FSCA"
"fsca fpul,%d0"
"&& !fpul_operand (operands[1], SImode)"
[(const_int 0)]
{
/* If operands[1] is something like (fix:SF (float:SF (reg:SI))) reduce it
to a simple reg, otherwise reload will have trouble reloading the
pseudo into fpul. */
rtx x = XEXP (operands[1], 0);
while (x != NULL_RTX && !fpul_operand (x, SImode))
{
gcc_assert (GET_CODE (x) == FIX || GET_CODE (x) == FLOAT);
x = XEXP (x, 0);
}
gcc_assert (x != NULL_RTX && fpul_operand (x, SImode));
emit_insn (gen_fsca (operands[0], x, operands[2], operands[3]));
DONE;
}
[(set_attr "type" "fsca")
(set_attr "fp_mode" "single")])
(define_expand "abssf2"
[(set (match_operand:SF 0 "fp_arith_reg_operand" "")
(abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]

View File

@ -1,3 +1,8 @@
2012-10-12 Oleg Endo <olegendo@gcc.gnu.org>
PR target/54680
* gcc.target/sh/pr54680.c: New.
2012-10-12 Jan Hubicka <jh@suse.cz>
* gcc.dg/webizer.c: New testcase.

View File

@ -0,0 +1,66 @@
/* Verify that the fsca input value is not converted to float and then back
to int. Notice that we can't count just "lds" insns because mode switches
use "lds.l". */
/* { dg-do compile { target "sh*-*-*" } } */
/* { dg-options "-O2 -mfsca -funsafe-math-optimizations" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2*" "-m3*" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "fsca" 7 } } */
/* { dg-final { scan-assembler-times "shad" 1 } } */
/* { dg-final { scan-assembler-times "lds\t" 6 } } */
/* { dg-final { scan-assembler-times "fmul" 2 } } */
/* { dg-final { scan-assembler-times "ftrc" 1 } } */
#include <math.h>
static const float pi = 3.14159265359f;
float
test00 (int x)
{
/* 1x shad, 1x lds, 1x fsca */
return sinf ( (x >> 8) * (2*pi) / (1 << 16));
}
float
test01 (int x)
{
/* 1x lds, 1x fsca */
return sinf (x * (2*pi) / 65536);
}
float
test02 (int x)
{
/* 1x lds, 1x fsca */
return sinf (x * (2*pi / 65536));
}
float
test03 (int x)
{
/* 1x lds, 1x fsca */
float scale = 2*pi / 65536;
return sinf (x * scale);
}
float
test04 (int x)
{
/* 1x lds, 1x fsca */
return cosf (x / 65536.0f * 2*pi);
}
float
test05 (int x)
{
/* 1x lds, 1x fsca, 1x fmul */
float scale = 2*pi / 65536;
return sinf (x * scale) * cosf (x * scale);
}
float
test_06 (float x)
{
/* 1x fmul, 1x ftrc, 1x fsca */
return sinf (x);
}