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:
parent
535269f4f9
commit
db292b0ecd
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" "")))]
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue