From: Jivan Hakobyan <jivanhakobyan9@gmail.com>
To: GCC Patches <gcc-patches@gcc.gnu.org>, Jeff Law <jlaw@ventanamicro.com>
Subject: RISC-V: Use convert instructions instead of calling library functions
Date: Mon, 18 Mar 2024 13:09:58 +0400 [thread overview]
Message-ID: <CAHso6sOn=SgKoaG1pwXHRLTXtvqpGY_RoKSjLfFaYTm313GvVQ@mail.gmail.com> (raw)
[-- Attachment #1.1: Type: text/plain, Size: 2368 bytes --]
As RV has round instructions it is reasonable to use them instead of
calling the library functions.
With my patch for the following C code:
double foo(double a) {
return ceil(a);
}
GCC generates the following ASM code (before it was tail call)
foo:
fabs.d fa4,fa0
lui a5,%hi(.LC0)
fld fa3,%lo(.LC0)(a5)
flt.d a5,fa4,fa3
beq a5,zero,.L3
fcvt.l.d a5,fa0,rup
fcvt.d.l fa4,a5
fsgnj.d fa0,fa4,fa0
.L3:
ret
.LC0:
.word 0
.word 1127219200 // 0x4330000000000000
The patch I have evaluated on SPEC2017.
Counted dynamic instructions counts and got the following improvements
510.parest_r 262 m -
511.povray_r 2.1 b 0.04%
521.wrt_r 269 m -
526.blender_r 3 b 0.1%
527.cam4_r 15 b 0.6%
538.imagick_r 365 b 7.6%
Overall executed 385 billion fewer instructions which is 0.5%.
gcc/ChangeLog:
* config/riscv/iterators.md (fix_ops, fix_uns): New iterators for
fix patterns.
(RINT, rint_pattern, rint_rm): Removed.
* config/riscv/riscv-protos.h (get_fp_rounding_coefficient): Add
function declaration.
* config/riscv/riscv-v.cc (get_fp_rounding_coefficient): Turned to
not static
* config/riscv/riscv.md (UNSPEC_LROUND): Removed.
(<fix_uns>_trunc<ANYF:mode>si2, lrint<ANYF:mode>si2): New expanders.
(l<round_pattern><ANYF:mode>si2,
<round_pattern><ANYF:mode>2): Likewise.
(<fix_uns>_trunc<ANYF:mode>si2_sext,
lrint<ANYF:mode>si2_sext): Expose generator.
(l<round_pattern><ANYF:mode>si2_sext): Likewise.
(<fix_uns>_trunc<ANYF:mode>si2, lrint<ANYF:mode>si2): Hide
generator.
(l<round_pattern><ANYF:mode>si2): Hide generator.
(fix_trunc<ANYF:mode><GPR:mode>2,
fixuns_trunc<ANYF:mode><GPR:mode>2): Removed.
(l<rint_pattern><ANYF:mode><GPR:mode>2,
<round_pattern><ANYF:mode>2): Likewise.
(<fix_uns>_trunc<ANYF:mode>di2, lrint<ANYF:mode>di2): New patterns.
(l<round_pattern><ANYF:mode>di2): Likewise.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/fix.c: New test.
* gcc.target/riscv/round.c: Likewise.
* gcc.target/riscv/round_32.c: Likewise.
* gcc.target/riscv/round_64.c: Likewise.
--
With the best regards
Jivan Hakobyan
[-- Attachment #2: round.diff --]
[-- Type: text/x-patch, Size: 19600 bytes --]
diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md
index a7694137685aee97ca249c0e720afdfc62ec33c9..75e119e407a36c273eaa6e5ffab24be42af7a8d7 100644
--- a/gcc/config/riscv/iterators.md
+++ b/gcc/config/riscv/iterators.md
@@ -196,6 +196,13 @@
(define_code_iterator bitmanip_rotate [rotate rotatert])
+;; These code iterators allow the signed and unsigned fix operations to use
+;; the same template.
+(define_code_iterator fix_ops [fix unsigned_fix])
+
+(define_code_attr fix_uns [(fix "fix") (unsigned_fix "fixuns")])
+
+
;; -------------------------------------------------------------------
;; Code Attributes
;; -------------------------------------------------------------------
@@ -312,11 +319,6 @@
;; Int Iterators.
;; -------------------------------------------------------------------
-;; Iterator and attributes for floating-point rounding instructions.
-(define_int_iterator RINT [UNSPEC_LRINT UNSPEC_LROUND])
-(define_int_attr rint_pattern [(UNSPEC_LRINT "rint") (UNSPEC_LROUND "round")])
-(define_int_attr rint_rm [(UNSPEC_LRINT "dyn") (UNSPEC_LROUND "rmm")])
-
;; Iterator and attributes for quiet comparisons.
(define_int_iterator QUIET_COMPARISON [UNSPEC_FLT_QUIET UNSPEC_FLE_QUIET])
(define_int_attr quiet_pattern [(UNSPEC_FLT_QUIET "lt") (UNSPEC_FLE_QUIET "le")])
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index b87355938052a3a0ca9107774bb3a683c85b74d9..03486f4c4e3dab733e48a702c4ffbb5865f1884d 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -709,6 +709,7 @@ bool gather_scatter_valid_offset_p (machine_mode);
HOST_WIDE_INT estimated_poly_value (poly_int64, unsigned int);
bool whole_reg_to_reg_move_p (rtx *, machine_mode, int);
bool splat_to_scalar_move_p (rtx *);
+rtx get_fp_rounding_coefficient (machine_mode);
}
/* We classify builtin types into two classes:
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 967f4e382875dfeee7d5de5ab05a2b537766844e..95a233dea44168dec2a28c9ffff4a46004a40e18 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -4494,7 +4494,7 @@ vls_mode_valid_p (machine_mode vls_mode)
All double floating point will be unchanged for ceil if it is
greater than and equal to 4503599627370496.
*/
-static rtx
+rtx
get_fp_rounding_coefficient (machine_mode inner_mode)
{
REAL_VALUE_TYPE real;
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index b16ed97909c04456ce4fe5234a82c5597549b67d..d4eb440d7baeb3d71c7e58291ce4136da6852246 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -64,7 +64,6 @@
UNSPEC_ROUNDEVEN
UNSPEC_NEARBYINT
UNSPEC_LRINT
- UNSPEC_LROUND
UNSPEC_FMIN
UNSPEC_FMAX
UNSPEC_FMINM
@@ -1967,21 +1966,48 @@
;;
;; ....................
-(define_insn "fix_trunc<ANYF:mode><GPR:mode>2"
- [(set (match_operand:GPR 0 "register_operand" "=r")
- (fix:GPR
+(define_expand "<fix_uns>_trunc<ANYF:mode>si2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (fix_ops:SI
(match_operand:ANYF 1 "register_operand" " f")))]
"TARGET_HARD_FLOAT || TARGET_ZFINX"
- "fcvt.<GPR:ifmt>.<ANYF:fmt> %0,%1,rtz"
+{
+ if (TARGET_64BIT)
+ {
+ rtx t = gen_reg_rtx (DImode);
+ emit_insn (gen_<fix_uns>_trunc<ANYF:mode>si2_sext (t, operands[1]));
+ t = gen_lowpart (SImode, t);
+ SUBREG_PROMOTED_VAR_P (t) = 1;
+ SUBREG_PROMOTED_SET (t, SRP_SIGNED);
+ emit_move_insn (operands[0], t);
+ DONE;
+ }
+})
+
+(define_insn "*<fix_uns>_trunc<ANYF:mode>si2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (fix_ops:SI
+ (match_operand:ANYF 1 "register_operand" " f")))]
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
+ "fcvt.w<u>.<ANYF:fmt> %0,%1,rtz"
+ [(set_attr "type" "fcvt_f2i")
+ (set_attr "mode" "<ANYF:MODE>")])
+
+(define_insn "<fix_uns>_trunc<ANYF:mode>si2_sext"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (sign_extend:DI (fix_ops:SI
+ (match_operand:ANYF 1 "register_operand" " f"))))]
+ "TARGET_64BIT && (TARGET_HARD_FLOAT || TARGET_ZFINX)"
+ "fcvt.w<u>.<ANYF:fmt> %0,%1,rtz"
[(set_attr "type" "fcvt_f2i")
(set_attr "mode" "<ANYF:MODE>")])
-(define_insn "fixuns_trunc<ANYF:mode><GPR:mode>2"
- [(set (match_operand:GPR 0 "register_operand" "=r")
- (unsigned_fix:GPR
+(define_insn "<fix_uns>_trunc<ANYF:mode>di2"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (fix_ops:DI
(match_operand:ANYF 1 "register_operand" " f")))]
- "TARGET_HARD_FLOAT || TARGET_ZFINX"
- "fcvt.<GPR:ifmt>u.<ANYF:fmt> %0,%1,rtz"
+ "TARGET_64BIT && (TARGET_HARD_FLOAT || TARGET_ZFINX)"
+ "fcvt.l<u>.<ANYF:fmt> %0,%1,rtz"
[(set_attr "type" "fcvt_f2i")
(set_attr "mode" "<ANYF:MODE>")])
@@ -2003,17 +2029,170 @@
[(set_attr "type" "fcvt_i2f")
(set_attr "mode" "<ANYF:MODE>")])
-(define_insn "l<rint_pattern><ANYF:mode><GPR:mode>2"
- [(set (match_operand:GPR 0 "register_operand" "=r")
- (unspec:GPR
+(define_expand "lrint<ANYF:mode>si2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI
[(match_operand:ANYF 1 "register_operand" " f")]
- RINT))]
+ UNSPEC_LRINT))]
"TARGET_HARD_FLOAT || TARGET_ZFINX"
- "fcvt.<GPR:ifmt>.<ANYF:fmt> %0,%1,<rint_rm>"
+{
+ if (TARGET_64BIT)
+ {
+ rtx t = gen_reg_rtx (DImode);
+ emit_insn (gen_lrint<ANYF:mode>si2_sext (t, operands[1]));
+ t = gen_lowpart (SImode, t);
+ SUBREG_PROMOTED_VAR_P (t) = 1;
+ SUBREG_PROMOTED_SET (t, SRP_SIGNED);
+ emit_move_insn (operands[0], t);
+ DONE;
+ }
+})
+
+(define_insn "*lrint<ANYF:mode>si2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI
+ [(match_operand:ANYF 1 "register_operand" " f")]
+ UNSPEC_LRINT))]
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
+ "fcvt.w.<ANYF:fmt> %0,%1,dyn"
[(set_attr "type" "fcvt_f2i")
(set_attr "mode" "<ANYF:MODE>")])
-(define_insn "<round_pattern><ANYF:mode>2"
+(define_insn "lrint<ANYF:mode>si2_sext"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (sign_extend:DI (unspec:SI
+ [(match_operand:ANYF 1 "register_operand" " f")]
+ UNSPEC_LRINT)))]
+ "TARGET_64BIT && (TARGET_HARD_FLOAT || TARGET_ZFINX)"
+ "fcvt.w.<ANYF:fmt> %0,%1,dyn"
+ [(set_attr "type" "fcvt_f2i")
+ (set_attr "mode" "<ANYF:MODE>")])
+
+(define_insn "lrint<ANYF:mode>di2"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI
+ [(match_operand:ANYF 1 "register_operand" " f")]
+ UNSPEC_LRINT))]
+ "TARGET_64BIT && (TARGET_HARD_FLOAT || TARGET_ZFINX)"
+ "fcvt.l.<ANYF:fmt> %0,%1,dyn"
+ [(set_attr "type" "fcvt_f2i")
+ (set_attr "mode" "<ANYF:MODE>")])
+
+(define_expand "l<round_pattern><ANYF:mode>si2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI
+ [(match_operand:ANYF 1 "register_operand" " f")]
+ ROUND))]
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
+{
+ if (TARGET_64BIT)
+ {
+ rtx t = gen_reg_rtx (DImode);
+ emit_insn (gen_l<round_pattern><ANYF:mode>si2_sext (t, operands[1]));
+ t = gen_lowpart (SImode, t);
+ SUBREG_PROMOTED_VAR_P (t) = 1;
+ SUBREG_PROMOTED_SET (t, SRP_SIGNED);
+ emit_move_insn (operands[0], t);
+ DONE;
+ }
+})
+
+(define_insn "*l<round_pattern><ANYF:mode>si2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI
+ [(match_operand:ANYF 1 "register_operand" " f")]
+ ROUND))]
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
+ "fcvt.w.<ANYF:fmt> %0,%1,<round_rm>"
+ [(set_attr "type" "fcvt_f2i")
+ (set_attr "mode" "<ANYF:MODE>")])
+
+(define_insn "l<round_pattern><ANYF:mode>si2_sext"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (sign_extend:DI (unspec:SI
+ [(match_operand:ANYF 1 "register_operand" " f")]
+ ROUND)))]
+ "TARGET_64BIT && (TARGET_HARD_FLOAT || TARGET_ZFINX)"
+ "fcvt.w.<ANYF:fmt> %0,%1,<round_rm>"
+ [(set_attr "type" "fcvt_f2i")
+ (set_attr "mode" "<ANYF:MODE>")])
+
+(define_insn "l<round_pattern><ANYF:mode>di2"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI
+ [(match_operand:ANYF 1 "register_operand" " f")]
+ ROUND))]
+ "TARGET_64BIT && (TARGET_HARD_FLOAT || TARGET_ZFINX)"
+ "fcvt.l.<ANYF:fmt> %0,%1,<round_rm>"
+ [(set_attr "type" "fcvt_f2i")
+ (set_attr "mode" "<ANYF:MODE>")])
+
+(define_expand "<round_pattern><ANYF:mode>2"
+ [(set (match_operand:ANYF 0 "register_operand" "=f")
+ (unspec:ANYF
+ [(match_operand:ANYF 1 "register_operand" " f")]
+ ROUND))]
+ "TARGET_HARD_FLOAT && (TARGET_ZFA
+ || flag_fp_int_builtin_inexact || !flag_trapping_math)"
+{
+ if (TARGET_ZFA)
+ emit_insn (gen_<round_pattern><ANYF:mode>_zfa2 (operands[0],
+ operands[1]));
+ else
+ {
+ rtx reg;
+ rtx label = 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);
+
+ riscv_emit_move (tmp_reg, operands[1]);
+ 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]));
+
+ riscv_expand_conditional_branch (label, LT, abs_reg, coeff_reg);
+
+ emit_jump_insn (gen_jump (end_label));
+ emit_barrier ();
+
+ emit_label (label);
+ switch (<ANYF:MODE>mode)
+ {
+ case SFmode:
+ reg = gen_reg_rtx (SImode);
+ emit_insn (gen_l<round_pattern>sfsi2 (reg, operands[1]));
+ emit_insn (gen_floatsisf2 (abs_reg, reg));
+ break;
+ case DFmode:
+ if (TARGET_64BIT)
+ {
+ reg = gen_reg_rtx (DImode);
+ emit_insn (gen_l<round_pattern>dfdi2 (reg, operands[1]));
+ emit_insn (gen_floatdidf2 (abs_reg, reg));
+ }
+ else
+ {
+ reg = gen_reg_rtx (SImode);
+ emit_insn (gen_l<round_pattern>dfsi2 (reg, operands[1]));
+ emit_insn (gen_floatsidf2 (abs_reg, reg));
+ }
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ emit_insn (gen_copysign<ANYF:mode>3 (tmp_reg, abs_reg, operands[1]));
+
+ emit_label (end_label);
+ riscv_emit_move (operands[0], tmp_reg);
+ }
+
+ DONE;
+})
+
+(define_insn "<round_pattern><ANYF:mode>_zfa2"
[(set (match_operand:ANYF 0 "register_operand" "=f")
(unspec:ANYF
[(match_operand:ANYF 1 "register_operand" " f")]
diff --git a/gcc/testsuite/gcc.target/riscv/fix.c b/gcc/testsuite/gcc.target/riscv/fix.c
new file mode 100644
index 0000000000000000000000000000000000000000..265a7da1fc5d49cfbe8f3459407c7fa787b747dd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/fix.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } } */
+
+int
+foo (double n)
+{
+ return n;
+}
+
+int
+foo_1 (float n)
+{
+ return n;
+}
+
+unsigned int
+foo_2 (double n)
+{
+ return n;
+}
+
+unsigned int
+foo_3 (float n)
+{
+ return n;
+}
+
+/* { dg-final { scan-assembler-times {\mfcvt.w.d} 1 } } */
+/* { dg-final { scan-assembler-times {\mfcvt.w.s} 1 } } */
+/* { dg-final { scan-assembler-times {\mfcvt.wu.d} 1 } } */
+/* { dg-final { scan-assembler-times {\mfcvt.wu.s} 1 } } */
+/* { dg-final { scan-assembler-not "\\ssext.w\\s" } } */
+
diff --git a/gcc/testsuite/gcc.target/riscv/round.c b/gcc/testsuite/gcc.target/riscv/round.c
new file mode 100644
index 0000000000000000000000000000000000000000..decfc82a390e8f89bdc839cd00b0cb451030e4c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/round.c
@@ -0,0 +1,144 @@
+#include <math.h>
+
+extern void abort (void);
+extern void exit (int);
+
+#define NEQ(a, b) (fabs((a) - (b)) > 0.000001)
+
+#define DECL_FUNC(TYPE1, TYPE2, ROUND) \
+ __attribute__ ((noinline, noclone)) TYPE2 \
+ convert_##TYPE1##_to_##TYPE2##_##ROUND (TYPE1 N) \
+ { \
+ return ROUND (N); \
+ }
+
+#define DECL_ALL_ROUNDS_FOR(ROUND_FUNC) \
+ DECL_FUNC(float, float, ROUND_FUNC) \
+ DECL_FUNC(double, double, ROUND_FUNC) \
+ DECL_FUNC(double, int, ROUND_FUNC) \
+ DECL_FUNC(double, long, ROUND_FUNC) \
+ DECL_FUNC(float, int, ROUND_FUNC) \
+ DECL_FUNC(float, long, ROUND_FUNC)
+
+
+DECL_ALL_ROUNDS_FOR(round)
+DECL_ALL_ROUNDS_FOR(ceil)
+DECL_ALL_ROUNDS_FOR(floor)
+DECL_ALL_ROUNDS_FOR(trunc)
+DECL_ALL_ROUNDS_FOR(nearbyint)
+
+#define TEST_ROUND(TYPE1, TYPE2, N, N_R, ROUND) \
+ if (NEQ (convert_##TYPE1##_to_##TYPE2##_##ROUND (N), N_R)) \
+ abort ();
+
+
+int main () {
+
+ /* Round */
+ TEST_ROUND(double, double, -4.8, -5.0, round);
+ TEST_ROUND(double, double, -4.2, -4.0, round);
+ TEST_ROUND(double, double, 4.8, 5.0, round);
+ TEST_ROUND(double, double, 4.2, 4.0, round);
+
+ TEST_ROUND(double, int, -4.8, -5, round);
+ TEST_ROUND(double, int, -4.2, -4, round);
+ TEST_ROUND(double, int, 4.8, 5, round);
+ TEST_ROUND(double, int, 4.2, 4, round);
+
+ TEST_ROUND(double, long, -4.8, -5, round);
+ TEST_ROUND(double, long, -4.2, -4, round);
+ TEST_ROUND(double, long, 4.8, 5, round);
+ TEST_ROUND(double, long, 4.2, 4, round);
+
+ TEST_ROUND(float, long, -4.8, -5, round);
+ TEST_ROUND(float, long, -4.2, -4, round);
+ TEST_ROUND(float, long, 4.8, 5, round);
+ TEST_ROUND(float, long, 4.2, 4, round);
+
+ /* Ceil */
+ TEST_ROUND(double, double, -4.8, -4.0, ceil);
+ TEST_ROUND(double, double, -4.2, -4.0, ceil);
+ TEST_ROUND(double, double, 4.8, 5.0, ceil);
+ TEST_ROUND(double, double, 4.2, 5.0, ceil);
+
+ TEST_ROUND(double, int, -4.8, -4, ceil);
+ TEST_ROUND(double, int, -4.2, -4, ceil);
+ TEST_ROUND(double, int, 4.8, 5, ceil);
+ TEST_ROUND(double, int, 4.2, 5, ceil);
+
+ TEST_ROUND(double, long, -4.8, -4, ceil);
+ TEST_ROUND(double, long, -4.2, -4, ceil);
+ TEST_ROUND(double, long, 4.8, 5, ceil);
+ TEST_ROUND(double, long, 4.2, 5, ceil);
+
+ TEST_ROUND(float, long, -4.8, -4, ceil);
+ TEST_ROUND(float, long, -4.2, -4, ceil);
+ TEST_ROUND(float, long, 4.8, 5, ceil);
+ TEST_ROUND(float, long, 4.2, 5, ceil);
+
+ /* Floor */
+ TEST_ROUND(double, double, -4.8, -5.0, floor);
+ TEST_ROUND(double, double, -4.2, -5.0, floor);
+ TEST_ROUND(double, double, 4.8, 4.0, floor);
+ TEST_ROUND(double, double, 4.2, 4.0, floor);
+
+ TEST_ROUND(double, int, -4.8, -5, floor);
+ TEST_ROUND(double, int, -4.2, -5, floor);
+ TEST_ROUND(double, int, 4.8, 4, floor);
+ TEST_ROUND(double, int, 4.2, 4, floor);
+
+ TEST_ROUND(double, long, -4.8, -5, floor);
+ TEST_ROUND(double, long, -4.2, -5, floor);
+ TEST_ROUND(double, long, 4.8, 4, floor);
+ TEST_ROUND(double, long, 4.2, 4, floor);
+
+ TEST_ROUND(float, long, -4.8, -5, floor);
+ TEST_ROUND(float, long, -4.2, -5, floor);
+ TEST_ROUND(float, long, 4.8, 4, floor);
+ TEST_ROUND(float, long, 4.2, 4, floor);
+
+ /* Trunc */
+ TEST_ROUND(double, double, -4.8, -4.0, trunc);
+ TEST_ROUND(double, double, -4.2, -4.0, trunc);
+ TEST_ROUND(double, double, 4.8, 4.0, trunc);
+ TEST_ROUND(double, double, 4.2, 4.0, trunc);
+
+ TEST_ROUND(double, int, -4.8, -4, trunc);
+ TEST_ROUND(double, int, -4.2, -4, trunc);
+ TEST_ROUND(double, int, 4.8, 4, trunc);
+ TEST_ROUND(double, int, 4.2, 4, trunc);
+
+ TEST_ROUND(double, long, -4.8, -4, trunc);
+ TEST_ROUND(double, long, -4.2, -4, trunc);
+ TEST_ROUND(double, long, 4.8, 4, trunc);
+ TEST_ROUND(double, long, 4.2, 4, trunc);
+
+ TEST_ROUND(float, long, -4.8, -4, trunc);
+ TEST_ROUND(float, long, -4.2, -4, trunc);
+ TEST_ROUND(float, long, 4.8, 4, trunc);
+ TEST_ROUND(float, long, 4.2, 4, trunc);
+
+ /* Nearbyint */
+ TEST_ROUND(double, double, -4.8, -5.0, nearbyint);
+ TEST_ROUND(double, double, -4.2, -4.0, nearbyint);
+ TEST_ROUND(double, double, 4.8, 5.0, nearbyint);
+ TEST_ROUND(double, double, 4.2, 4.0, nearbyint);
+
+ TEST_ROUND(double, int, -4.8, -5, nearbyint);
+ TEST_ROUND(double, int, -4.2, -4, nearbyint);
+ TEST_ROUND(double, int, 4.8, 5, nearbyint);
+ TEST_ROUND(double, int, 4.2, 4, nearbyint);
+
+ TEST_ROUND(double, long, -4.8, -5, nearbyint);
+ TEST_ROUND(double, long, -4.2, -4, nearbyint);
+ TEST_ROUND(double, long, 4.8, 5, nearbyint);
+ TEST_ROUND(double, long, 4.2, 4, nearbyint);
+
+ TEST_ROUND(float, long, -4.8, -5, nearbyint);
+ TEST_ROUND(float, long, -4.2, -4, nearbyint);
+ TEST_ROUND(float, long, 4.8, 5, nearbyint);
+ TEST_ROUND(float, long, 4.2, 4, nearbyint);
+
+ exit(0);
+}
+
diff --git a/gcc/testsuite/gcc.target/riscv/round_32.c b/gcc/testsuite/gcc.target/riscv/round_32.c
new file mode 100644
index 0000000000000000000000000000000000000000..f9fea70ad5523c76c98bd2c20ce4d17db98b8b79
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/round_32.c
@@ -0,0 +1,22 @@
+/* { dg-do compile { target { riscv32*-*-* } } } */
+/* { dg-options "-march=rv32gc -mabi=ilp32d -fno-math-errno -funsafe-math-optimizations -fno-inline" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+#include "round.c"
+
+/* { dg-final { scan-assembler-times {\mfcvt.w.s} 15 } } */
+/* { dg-final { scan-assembler-times {\mfcvt.s.w} 5 } } */
+/* { dg-final { scan-assembler-times {\mfcvt.d.w} 65 } } */
+/* { dg-final { scan-assembler-times {\mfcvt.w.d} 15 } } */
+/* { dg-final { scan-assembler-times {,rup} 6 } } */
+/* { dg-final { scan-assembler-times {,rmm} 6 } } */
+/* { dg-final { scan-assembler-times {,rdn} 6 } } */
+/* { dg-final { scan-assembler-times {,rtz} 6 } } */
+/* { dg-final { scan-assembler-not {\mfcvt.l.d} } } */
+/* { dg-final { scan-assembler-not {\mfcvt.d.l} } } */
+/* { dg-final { scan-assembler-not "\\sceil\\s" } } */
+/* { dg-final { scan-assembler-not "\\sfloor\\s" } } */
+/* { dg-final { scan-assembler-not "\\sround\\s" } } */
+/* { dg-final { scan-assembler-not "\\snearbyint\\s" } } */
+/* { dg-final { scan-assembler-not "\\srint\\s" } } */
+/* { dg-final { scan-assembler-not "\\stail\\s" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/round_64.c b/gcc/testsuite/gcc.target/riscv/round_64.c
new file mode 100644
index 0000000000000000000000000000000000000000..e79690979a50663c1c3518724cc23466d9e20490
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/round_64.c
@@ -0,0 +1,23 @@
+/* { dg-do compile { target { riscv64*-*-* } } } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -fno-math-errno -funsafe-math-optimizations -fno-inline" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+#include "round.c"
+
+/* { dg-final { scan-assembler-times {\mfcvt.w.s} 10 } } */
+/* { dg-final { scan-assembler-times {\mfcvt.s.w} 5 } } */
+/* { dg-final { scan-assembler-times {\mfcvt.l.d} 10 } } */
+/* { dg-final { scan-assembler-times {\mfcvt.d.l} 45 } } */
+/* { dg-final { scan-assembler-times {\mfcvt.w.d} 5 } } */
+/* { dg-final { scan-assembler-times {,rup} 6 } } */
+/* { dg-final { scan-assembler-times {,rmm} 6 } } */
+/* { dg-final { scan-assembler-times {,rdn} 6 } } */
+/* { dg-final { scan-assembler-times {,rtz} 6 } } */
+/* { dg-final { scan-assembler-not "\\sceil\\s" } } */
+/* { dg-final { scan-assembler-not "\\sfloor\\s" } } */
+/* { dg-final { scan-assembler-not "\\sround\\s" } } */
+/* { dg-final { scan-assembler-not "\\snearbyint\\s" } } */
+/* { dg-final { scan-assembler-not "\\srint\\s" } } */
+/* { dg-final { scan-assembler-not "\\stail\\s" } } */
+/* { dg-final { scan-assembler-not "\\ssext.w\\s" } } */
+
next reply other threads:[~2024-03-18 9:10 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-03-18 9:09 Jivan Hakobyan [this message]
2024-03-19 3:50 ` Jeff Law
2024-03-19 16:23 ` Palmer Dabbelt
2024-03-19 19:58 ` Andrew Waterman
2024-03-19 20:19 ` Palmer Dabbelt
2024-03-20 18:54 ` Jeff Law
2024-03-20 19:34 ` Palmer Dabbelt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CAHso6sOn=SgKoaG1pwXHRLTXtvqpGY_RoKSjLfFaYTm313GvVQ@mail.gmail.com' \
--to=jivanhakobyan9@gmail.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=jlaw@ventanamicro.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).