aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/config/riscv/riscv.md39
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/math-nearbyint-1.c4
2 files changed, 28 insertions, 15 deletions
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 843a048..78a01ef 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -2322,27 +2322,38 @@
else
{
rtx reg;
- rtx label = gen_label_rtx ();
+ rtx label1 = gen_label_rtx ();
+ rtx label2 = gen_label_rtx ();
+ rtx label3 = gen_label_rtx ();
rtx end_label = gen_label_rtx ();
rtx abs_reg = gen_reg_rtx (<ANYF:MODE>mode);
rtx coeff_reg = gen_reg_rtx (<ANYF:MODE>mode);
rtx tmp_reg = gen_reg_rtx (<ANYF:MODE>mode);
- rtx fflags = gen_reg_rtx (SImode);
riscv_emit_move (tmp_reg, operands[1]);
+
+ if (flag_trapping_math)
+ {
+ /* Check if the input is a NaN. */
+ riscv_expand_conditional_branch (label1, EQ,
+ operands[1], operands[1]);
+
+ emit_jump_insn (gen_jump (label3));
+ emit_barrier ();
+
+ emit_label (label1);
+ }
+
riscv_emit_move (coeff_reg,
riscv_vector::get_fp_rounding_coefficient (<ANYF:MODE>mode));
emit_insn (gen_abs<ANYF:mode>2 (abs_reg, operands[1]));
- /* fp compare can set invalid flag for NaN, so backup fflags. */
- if (flag_trapping_math)
- emit_insn (gen_riscv_frflags (fflags));
- riscv_expand_conditional_branch (label, LT, abs_reg, coeff_reg);
+ riscv_expand_conditional_branch (label2, LT, abs_reg, coeff_reg);
emit_jump_insn (gen_jump (end_label));
emit_barrier ();
- emit_label (label);
+ emit_label (label2);
switch (<ANYF:MODE>mode)
{
case SFmode:
@@ -2361,15 +2372,17 @@
emit_insn (gen_copysign<ANYF:mode>3 (tmp_reg, abs_reg, operands[1]));
- emit_label (end_label);
+ emit_jump_insn (gen_jump (end_label));
+ emit_barrier ();
- /* Restore fflags, but after label. This is slightly different
- than glibc implementation which only needs to restore under
- the label, since it checks for NaN first, meaning following fp
- compare can't raise fp exceptons and thus not clobber fflags. */
if (flag_trapping_math)
- emit_insn (gen_riscv_fsflags (fflags));
+ {
+ emit_label (label3);
+ /* Generate a qNaN from an sNaN if needed. */
+ emit_insn (gen_add<ANYF:mode>3 (tmp_reg, operands[1], operands[1]));
+ }
+ emit_label (end_label);
riscv_emit_move (operands[0], tmp_reg);
}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/math-nearbyint-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/math-nearbyint-1.c
index 89af160..bb62ce2 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/math-nearbyint-1.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/math-nearbyint-1.c
@@ -54,5 +54,5 @@ DEF_OP_V (nearbyint, 512, double, __builtin_nearbyint)
/* { dg-final { scan-tree-dump-not "4096,4096" "optimized" } } */
/* { dg-final { scan-assembler-times {vfcvt\.x\.f\.v\s+v[0-9]+,\s*v[0-9]+,\s*v0\.t} 30 } } */
/* { dg-final { scan-assembler-times {vfcvt\.f\.x\.v\s+v[0-9]+,\s*v[0-9]+,\s*v0\.t} 30 } } */
-/* { dg-final { scan-assembler-times {frflags\s+[atx][0-9]+} 32 } } */
-/* { dg-final { scan-assembler-times {fsflags\s+[atx][0-9]+} 32 } } */
+/* { dg-final { scan-assembler-times {frflags\s+[atx][0-9]+} 30 } } */
+/* { dg-final { scan-assembler-times {fsflags\s+[atx][0-9]+} 30 } } */