在 2023/11/20 上午8:47, Xi Ruoyao 写道:
The usage LSX and LASX frint/ftint instructions had some problems:
1. These instructions raises FE_INEXACT, which is not allowed with
-fno-fp-int-builtin-inexact for most C2x section F.10.6 functions
(the only exceptions are rint, lrint, and llrint).
2. The "frint" instruction without explicit rounding mode is used for
roundM2, this is incorrect because roundM2 is defined "rounding
operand 1 to the *nearest* integer, rounding away from zero in the
event of a tie". We actually don't have such an instruction. Our
frintrne instruction is roundevenM2 (unfortunately, this is not
documented).
3. These define_insn's are written in a way not so easy to hack.
So I removed these instructions and created a "simd.md" file, then added
them and the corresponding expanders there. The advantage of the
simd.md file is we don't need to duplicate the RTL template twice (in
lsx.md and lasx.md).
/* snip */
+;; fix_trunc is allowed to raise inexact exception even if
+;; -fno-fp-int-builtin-inexact. Because the middle end trys to match
+;; (FIX x) and it does not know (FIX (UNSPEC_SIMD_FRINTRZ x)), we need
+;; to use define_insn_and_split instead of define_expand (expanders are
+;; not considered during matching).
Hi,
I don’t quite understand this part. Is it because define_insn would be
duplicated with the above implementation,
so define_insn_and_split is used?
Thanks.
+(define_insn_and_split "fix_trunc<mode><vimode>2"
+ [(set (match_operand:<VIMODE> 0 "register_operand" "=f")
+ (fix:<VIMODE> (match_operand:FVEC 1 "register_operand" "f")))]
+ ""
+ "#"
+ ""
+ [(const_int 0)]
+ {
+ emit_insn (gen_<simd_isa>_<x>vftintrz_<simdifmt_for_f>_<simdfmt> (
+ operands[0], operands[1]));
+ DONE;
+ }
+ [(set_attr "type" "simd_fcvt")
+ (set_attr "mode" "<MODE>")])