diff options
author | Xi Ruoyao <xry111@xry111.site> | 2022-11-08 12:14:35 +0800 |
---|---|---|
committer | Xi Ruoyao <xry111@xry111.site> | 2022-11-12 15:01:13 +0800 |
commit | d26c757b2ec22d2d752af94908ce54a1266cca01 (patch) | |
tree | 975a8a0119a80e4550f7b35573e59b7aa0da5926 | |
parent | 51a233b97cc9c51e63f03f2f5554e905f3f6c054 (diff) | |
download | gcc-d26c757b2ec22d2d752af94908ce54a1266cca01.zip gcc-d26c757b2ec22d2d752af94908ce54a1266cca01.tar.gz gcc-d26c757b2ec22d2d752af94908ce54a1266cca01.tar.bz2 |
LoongArch: Add fscaleb.{s,d} instructions as ldexp{sf,df}3
This allows optimizing __builtin_ldexp{,f} and __builtin_scalbn{,f} with
-fno-math-errno.
IMODE is added because we can't hard code SI for operand 2: fscaleb.d
instruction always take the high half of both source registers into
account. See my_ldexp_long in the test case.
gcc/ChangeLog:
* config/loongarch/loongarch.md (UNSPEC_FSCALEB): New unspec.
(type): Add fscaleb.
(IMODE): New mode attr.
(ldexp<mode>3): New instruction template.
gcc/testsuite/ChangeLog:
* gcc.target/loongarch/fscaleb.c: New test.
-rw-r--r-- | gcc/config/loongarch/loongarch.md | 26 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/loongarch/fscaleb.c | 48 |
2 files changed, 72 insertions, 2 deletions
diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md index eb127c3..c141c9a 100644 --- a/gcc/config/loongarch/loongarch.md +++ b/gcc/config/loongarch/loongarch.md @@ -41,6 +41,7 @@ UNSPEC_FTINT UNSPEC_FTINTRM UNSPEC_FTINTRP + UNSPEC_FSCALEB ;; Override return address for exception handling. UNSPEC_EH_RETURN @@ -220,6 +221,7 @@ ;; fcmp floating point compare ;; fcopysign floating point copysign ;; fcvt floating point convert +;; fscaleb floating point scale ;; fsqrt floating point square root ;; frsqrt floating point reciprocal square root ;; multi multiword sequence (or user asm statements) @@ -231,8 +233,8 @@ "unknown,branch,jump,call,load,fpload,fpidxload,store,fpstore,fpidxstore, prefetch,prefetchx,condmove,mgtf,mftg,const,arith,logical, shift,slt,signext,clz,trap,imul,idiv,move, - fmove,fadd,fmul,fmadd,fdiv,frdiv,fabs,fneg,fcmp,fcopysign,fcvt,fsqrt, - frsqrt,accext,accmod,multi,atomic,syncloop,nop,ghost" + fmove,fadd,fmul,fmadd,fdiv,frdiv,fabs,fneg,fcmp,fcopysign,fcvt,fscaleb, + fsqrt,frsqrt,accext,accmod,multi,atomic,syncloop,nop,ghost" (cond [(eq_attr "jirl" "!unset") (const_string "call") (eq_attr "got" "load") (const_string "load") @@ -418,6 +420,10 @@ ;; the controlling mode. (define_mode_attr HALFMODE [(DF "SI") (DI "SI") (TF "DI")]) +;; This attribute gives the integer mode that has the same size of a +;; floating-point mode. +(define_mode_attr IMODE [(SF "SI") (DF "DI")]) + ;; This code iterator allows signed and unsigned widening multiplications ;; to use the same template. (define_code_iterator any_extend [sign_extend zero_extend]) @@ -1014,7 +1020,23 @@ "fcopysign.<fmt>\t%0,%1,%2" [(set_attr "type" "fcopysign") (set_attr "mode" "<UNITMODE>")]) + +;; +;; .................... +;; +;; FLOATING POINT SCALE +;; +;; .................... +(define_insn "ldexp<mode>3" + [(set (match_operand:ANYF 0 "register_operand" "=f") + (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f") + (match_operand:<IMODE> 2 "register_operand" "f")] + UNSPEC_FSCALEB))] + "TARGET_HARD_FLOAT" + "fscaleb.<fmt>\t%0,%1,%2" + [(set_attr "type" "fscaleb") + (set_attr "mode" "<UNITMODE>")]) ;; ;; ................... diff --git a/gcc/testsuite/gcc.target/loongarch/fscaleb.c b/gcc/testsuite/gcc.target/loongarch/fscaleb.c new file mode 100644 index 0000000..f18470f --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/fscaleb.c @@ -0,0 +1,48 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mabi=lp64d -mdouble-float -fno-math-errno" } */ +/* { dg-final { scan-assembler-times "fscaleb\\.s" 3 } } */ +/* { dg-final { scan-assembler-times "fscaleb\\.d" 4 } } */ +/* { dg-final { scan-assembler-times "slli\\.w" 1 } } */ + +double +my_scalbln (double a, long b) +{ + return __builtin_scalbln (a, b); +} + +double +my_scalbn (double a, int b) +{ + return __builtin_scalbn (a, b); +} + +double +my_ldexp (double a, int b) +{ + return __builtin_ldexp (a, b); +} + +float +my_scalblnf (float a, long b) +{ + return __builtin_scalblnf (a, b); +} + +float +my_scalbnf (float a, int b) +{ + return __builtin_scalbnf (a, b); +} + +float +my_ldexpf (float a, int b) +{ + return __builtin_ldexpf (a, b); +} + +/* b must be sign-extended */ +double +my_ldexp_long (double a, long b) +{ + return __builtin_ldexp (a, b); +} |