aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/loongarch
diff options
context:
space:
mode:
authorXi Ruoyao <xry111@xry111.site>2024-07-04 02:49:28 +0800
committerXi Ruoyao <xry111@xry111.site>2024-08-15 19:38:44 +0800
commitee4a6343225b6e44b3d2b2c90c355c21f7ec6855 (patch)
tree46fc1d502a2736b77c47841965b70250afd508df /gcc/config/loongarch
parentf7e672da8fc3d416a6d07eb01f3be4400ef94fac (diff)
downloadgcc-ee4a6343225b6e44b3d2b2c90c355c21f7ec6855.zip
gcc-ee4a6343225b6e44b3d2b2c90c355c21f7ec6855.tar.gz
gcc-ee4a6343225b6e44b3d2b2c90c355c21f7ec6855.tar.bz2
LoongArch: Implement scalar isinf, isnormal, and isfinite via fclass
Doing so can avoid loading FP constants from the memory. It also partially fixes PR 66262 as fclass does not signal on sNaN. gcc/ChangeLog: * config/loongarch/loongarch.md (extendsidi2): Add ("=r", "f") alternative and use movfr2gr.s for it. The spec clearly states movfr2gr.s sign extends the value to GRLEN. (fclass_<fmt>): Make the result SImode instead of a floating mode. The fclass results are really not FP values. (FCLASS_MASK): New define_int_iterator. (fclass_optab): New define_int_attr. (<FCLASS_MASK:fclass_optab><ANYF:mode>): New define_expand template. gcc/testsuite/ChangeLog: * gcc.target/loongarch/fclass-compile.c: New test. * gcc.target/loongarch/fclass-run.c: New test.
Diffstat (limited to 'gcc/config/loongarch')
-rw-r--r--gcc/config/loongarch/loongarch.md53
1 files changed, 46 insertions, 7 deletions
diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md
index 73cdb38..f70ca85 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -1851,16 +1851,17 @@
;; ....................
(define_insn "extendsidi2"
- [(set (match_operand:DI 0 "register_operand" "=r,r,r,r")
+ [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r")
(sign_extend:DI
- (match_operand:SI 1 "nonimmediate_operand" "r,ZC,m,k")))]
+ (match_operand:SI 1 "nonimmediate_operand" "r,ZC,m,k,f")))]
"TARGET_64BIT"
"@
slli.w\t%0,%1,0
ldptr.w\t%0,%1
ld.w\t%0,%1
- ldx.w\t%0,%1"
- [(set_attr "move_type" "sll0,load,load,load")
+ ldx.w\t%0,%1
+ movfr2gr.s\t%0,%1"
+ [(set_attr "move_type" "sll0,load,load,load,mftg")
(set_attr "mode" "DI")])
(define_insn "extend<SHORT:mode><GPR:mode>2"
@@ -4110,14 +4111,52 @@
"movgr2fcsr\t$r%0,%1")
(define_insn "fclass_<fmt>"
- [(set (match_operand:ANYF 0 "register_operand" "=f")
- (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f")]
- UNSPEC_FCLASS))]
+ [(set (match_operand:SI 0 "register_operand" "=f")
+ (unspec:SI [(match_operand:ANYF 1 "register_operand" "f")]
+ UNSPEC_FCLASS))]
"TARGET_HARD_FLOAT"
"fclass.<fmt>\t%0,%1"
[(set_attr "type" "unknown")
(set_attr "mode" "<MODE>")])
+(define_int_iterator FCLASS_MASK [68 136 952])
+(define_int_attr fclass_optab
+ [(68 "isinf")
+ (136 "isnormal")
+ (952 "isfinite")])
+
+(define_expand "<FCLASS_MASK:fclass_optab><ANYF:mode>2"
+ [(match_operand:SI 0 "register_operand" "=r")
+ (match_operand:ANYF 1 "register_operand" " f")
+ (const_int FCLASS_MASK)]
+ "TARGET_HARD_FLOAT"
+ {
+ rtx ft0 = gen_reg_rtx (SImode);
+ rtx t0 = gen_reg_rtx (word_mode);
+ rtx mask = GEN_INT (<FCLASS_MASK>);
+
+ emit_insn (gen_fclass_<ANYF:fmt> (ft0, operands[1]));
+
+ if (TARGET_64BIT)
+ emit_insn (gen_extend_insn (t0, ft0, DImode, SImode, 0));
+ else
+ emit_move_insn (t0, ft0);
+
+ emit_move_insn (t0, gen_rtx_AND (word_mode, t0, mask));
+ emit_move_insn (t0, gen_rtx_NE (word_mode, t0, const0_rtx));
+
+ if (TARGET_64BIT)
+ {
+ t0 = lowpart_subreg (SImode, t0, DImode);
+ SUBREG_PROMOTED_VAR_P (t0) = 1;
+ SUBREG_PROMOTED_SET (t0, SRP_SIGNED);
+ }
+
+ emit_move_insn (operands[0], t0);
+
+ DONE;
+ })
+
(define_insn "bytepick_w_<bytepick_imm>"
[(set (match_operand:SI 0 "register_operand" "=r")
(ior:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")