Hello. This was a mail in thread Re: Expanding roundeven on 19th June but as its gone far inside the thread, I thought of having a fresh one. The following patch expands roundeven with instruction vroundsd using -mavx option but without it is giving internal compiler error which I believe is due to reaching gcc_unreachable (). The doubts I had come up with : Test code compiled with attached patch:
double plusone (double d) { return __builtin_roundeven (d) + 1; } Compiling the program using -O2 gave internal compiler error which I believe is because gcc_unreachable() at: Inside : (define_expand "<rounding_insn><mode>2" There is a condition : if (TARGET_SSE4_1) emit_insn (gen_sse4_1_round<mode>2 (operands[0], operands[1], GEN_INT (ROUND_<ROUNDING> | ROUND_NO_EXC))); I think the above condition matches the criterion which Joseph previously mentioned? : > I think the code will be much clearer if it explicitly says > ROUND_ROUNDEVEN | ROUND_NO_EXC, else if (TARGET_64BIT || (<MODE>mode != DFmode)) { if (ROUND_<ROUNDING> == ROUND_FLOOR) ix86_expand_floorceil (operands[0], operands[1], true); else if (ROUND_<ROUNDING> == ROUND_CEIL) ix86_expand_floorceil (operands[0], operands[1], false); else if (ROUND_<ROUNDING> == ROUND_TRUNC) ix86_expand_trunc (operands[0], operands[1]); else gcc_unreachable (); } But with -mavx option, assembly generated the vroundsd insn. Does it mean ROUNDEVEN should have a condition in the above else if, but comments above ix86_expand* functions in i386-expand.c says that those are for SSE2 sequences? Thanks, -Tejas
diff --git a/gcc/config/i386/i386-builtin.def b/gcc/config/i386/i386-builtin.def index e547dda80f1..40536d7929c 100644 --- a/gcc/config/i386/i386-builtin.def +++ b/gcc/config/i386/i386-builtin.def @@ -906,6 +906,7 @@ BDESC (OPTION_MASK_ISA_SSE4_1, 0, CODE_FOR_sse4_1_roundpd, "__builtin_ia32_floor BDESC (OPTION_MASK_ISA_SSE4_1, 0, CODE_FOR_sse4_1_roundpd, "__builtin_ia32_ceilpd", IX86_BUILTIN_CEILPD, (enum rtx_code) ROUND_CEIL, (int) V2DF_FTYPE_V2DF_ROUND) BDESC (OPTION_MASK_ISA_SSE4_1, 0, CODE_FOR_sse4_1_roundpd, "__builtin_ia32_truncpd", IX86_BUILTIN_TRUNCPD, (enum rtx_code) ROUND_TRUNC, (int) V2DF_FTYPE_V2DF_ROUND) BDESC (OPTION_MASK_ISA_SSE4_1, 0, CODE_FOR_sse4_1_roundpd, "__builtin_ia32_rintpd", IX86_BUILTIN_RINTPD, (enum rtx_code) ROUND_MXCSR, (int) V2DF_FTYPE_V2DF_ROUND) +BDESC (OPTION_MASK_ISA_SSE4_1, 0, CODE_FOR_sse4_1_roundpd, "__builtin_ia32_roundevenpd", IX86_BUILTIN_ROUNDEVENPD, (enum rtx_code) ROUND_ROUNDEVEN, (int) V2DF_FTYPE_V2DF_ROUND) BDESC (OPTION_MASK_ISA_SSE4_1, 0, CODE_FOR_sse4_1_roundpd_vec_pack_sfix, "__builtin_ia32_floorpd_vec_pack_sfix", IX86_BUILTIN_FLOORPD_VEC_PACK_SFIX, (enum rtx_code) ROUND_FLOOR, (int) V4SI_FTYPE_V2DF_V2DF_ROUND) BDESC (OPTION_MASK_ISA_SSE4_1, 0, CODE_FOR_sse4_1_roundpd_vec_pack_sfix, "__builtin_ia32_ceilpd_vec_pack_sfix", IX86_BUILTIN_CEILPD_VEC_PACK_SFIX, (enum rtx_code) ROUND_CEIL, (int) V4SI_FTYPE_V2DF_V2DF_ROUND) @@ -917,6 +918,7 @@ BDESC (OPTION_MASK_ISA_SSE4_1, 0, CODE_FOR_sse4_1_roundps, "__builtin_ia32_floor BDESC (OPTION_MASK_ISA_SSE4_1, 0, CODE_FOR_sse4_1_roundps, "__builtin_ia32_ceilps", IX86_BUILTIN_CEILPS, (enum rtx_code) ROUND_CEIL, (int) V4SF_FTYPE_V4SF_ROUND) BDESC (OPTION_MASK_ISA_SSE4_1, 0, CODE_FOR_sse4_1_roundps, "__builtin_ia32_truncps", IX86_BUILTIN_TRUNCPS, (enum rtx_code) ROUND_TRUNC, (int) V4SF_FTYPE_V4SF_ROUND) BDESC (OPTION_MASK_ISA_SSE4_1, 0, CODE_FOR_sse4_1_roundps, "__builtin_ia32_rintps", IX86_BUILTIN_RINTPS, (enum rtx_code) ROUND_MXCSR, (int) V4SF_FTYPE_V4SF_ROUND) +BDESC (OPTION_MASK_ISA_SSE4_1, 0, CODE_FOR_sse4_1_roundps, "__builtin_ia32_roundevenps", IX86_BUILTIN_ROUNDEVENPS, (enum rtx_code) ROUND_ROUNDEVEN, (int) V4SF_FTYPE_V4SF_ROUND) BDESC (OPTION_MASK_ISA_SSE4_1, 0, CODE_FOR_sse4_1_roundps_sfix, "__builtin_ia32_floorps_sfix", IX86_BUILTIN_FLOORPS_SFIX, (enum rtx_code) ROUND_FLOOR, (int) V4SI_FTYPE_V4SF_ROUND) BDESC (OPTION_MASK_ISA_SSE4_1, 0, CODE_FOR_sse4_1_roundps_sfix, "__builtin_ia32_ceilps_sfix", IX86_BUILTIN_CEILPS_SFIX, (enum rtx_code) ROUND_CEIL, (int) V4SI_FTYPE_V4SF_ROUND) diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 01213ccb82c..ce58b5e5c28 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -2468,6 +2468,7 @@ enum ix86_stack_slot SLOT_CW_TRUNC, SLOT_CW_FLOOR, SLOT_CW_CEIL, + SLOT_CW_ROUNDEVEN, SLOT_STV_TEMP, MAX_386_STACK_LOCALS }; @@ -2479,6 +2480,7 @@ enum ix86_entity I387_TRUNC, I387_FLOOR, I387_CEIL, + I387_ROUNDEVEN, MAX_386_ENTITIES }; diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 01338e294ab..b11af2f4308 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -144,6 +144,7 @@ UNSPEC_FRNDINT_FLOOR UNSPEC_FRNDINT_CEIL UNSPEC_FRNDINT_TRUNC + UNSPEC_FRNDINT_ROUNDEVEN UNSPEC_FIST_FLOOR UNSPEC_FIST_CEIL @@ -303,7 +304,8 @@ ;; Constants to represent rounding modes in the ROUND instruction (define_constants - [(ROUND_FLOOR 0x1) + [(ROUND_ROUNDEVEN 0x0) + (ROUND_FLOOR 0x1) (ROUND_CEIL 0x2) (ROUND_TRUNC 0x3) (ROUND_MXCSR 0x4) @@ -779,7 +781,7 @@ ;; Defines rounding mode of an FP operation. -(define_attr "i387_cw" "trunc,floor,ceil,uninitialized,any" +(define_attr "i387_cw" "trunc,floor,ceil,roundeven,uninitialized,any" (const_string "any")) ;; Define attribute to indicate AVX insns with partial XMM register update. @@ -16254,7 +16256,8 @@ (define_int_iterator FRNDINT_ROUNDING [UNSPEC_FRNDINT_FLOOR UNSPEC_FRNDINT_CEIL - UNSPEC_FRNDINT_TRUNC]) + UNSPEC_FRNDINT_TRUNC + UNSPEC_FRNDINT_ROUNDEVEN]) (define_int_iterator FIST_ROUNDING [UNSPEC_FIST_FLOOR @@ -16265,6 +16268,7 @@ [(UNSPEC_FRNDINT_FLOOR "floor") (UNSPEC_FRNDINT_CEIL "ceil") (UNSPEC_FRNDINT_TRUNC "btrunc") + (UNSPEC_FRNDINT_ROUNDEVEN "roundeven") (UNSPEC_FIST_FLOOR "floor") (UNSPEC_FIST_CEIL "ceil")]) @@ -16272,6 +16276,7 @@ [(UNSPEC_FRNDINT_FLOOR "floor") (UNSPEC_FRNDINT_CEIL "ceil") (UNSPEC_FRNDINT_TRUNC "trunc") + (UNSPEC_FRNDINT_ROUNDEVEN "roundeven") (UNSPEC_FIST_FLOOR "floor") (UNSPEC_FIST_CEIL "ceil")]) @@ -16279,6 +16284,7 @@ [(UNSPEC_FRNDINT_FLOOR "FLOOR") (UNSPEC_FRNDINT_CEIL "CEIL") (UNSPEC_FRNDINT_TRUNC "TRUNC") + (UNSPEC_FRNDINT_ROUNDEVEN "ROUNDEVEN") (UNSPEC_FIST_FLOOR "FLOOR") (UNSPEC_FIST_CEIL "CEIL")]) diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def index 016301a58d8..c07d48594e3 100644 --- a/gcc/internal-fn.def +++ b/gcc/internal-fn.def @@ -231,6 +231,7 @@ DEF_INTERNAL_FLT_FLOATN_FN (FLOOR, ECF_CONST, floor, unary) DEF_INTERNAL_FLT_FLOATN_FN (NEARBYINT, ECF_CONST, nearbyint, unary) DEF_INTERNAL_FLT_FLOATN_FN (RINT, ECF_CONST, rint, unary) DEF_INTERNAL_FLT_FLOATN_FN (ROUND, ECF_CONST, round, unary) +DEF_INTERNAL_FLT_FLOATN_FN (ROUNDEVEN, ECF_CONST, roundeven, unary) DEF_INTERNAL_FLT_FLOATN_FN (TRUNC, ECF_CONST, btrunc, unary) /* Binary math functions. */ diff --git a/gcc/optabs.def b/gcc/optabs.def index 8af3a2f43fd..839d250b8c6 100644 --- a/gcc/optabs.def +++ b/gcc/optabs.def @@ -267,6 +267,7 @@ OPTAB_D (fnms_optab, "fnms$a4") OPTAB_D (rint_optab, "rint$a2") OPTAB_D (round_optab, "round$a2") +OPTAB_D (roundeven_optab, "roundeven$a2") OPTAB_D (floor_optab, "floor$a2") OPTAB_D (ceil_optab, "ceil$a2") OPTAB_D (btrunc_optab, "btrunc$a2")