I've applied this patch to C11-atomic branch to add support for handling x87 floating-point exceptions for atomic compound assignment. With this applied, c11-atomic-exec-5.c now passes on x86_64-unknown-linux-gnu. I consider the branch now feature-complete regarding _Atomic support (as opposed to stdatomic.h) so the next step will be preparing the relevant parts of the branch for submission for trunk.
2013-11-05 Joseph Myers <jos...@codesourcery.com> * config/i386/i386-builtin-types.def (VOID_FTYPE_PUSHORT): New function type. * config/i386/i386.c (enum ix86_builtins): Add IX86_BUILTIN_FNSTENV, IX86_BUILTIN_FLDENV, IX86_BUILTIN_FNSTSW and IX86_BUILTIN_FNCLEX. (bdesc_special_args): Add __builtin_ia32_fnstenv, __builtin_ia32_fldenv, __builtin_ia32_fnstsw and __builtin_ia32_fnclex. (ix86_expand_builtin): Handle the new built-in functions. (ix86_atomic_assign_expand_fenv): Handle x87 floating-point state. * config/i386/i386.md (UNSPECV_FNSTENV, UNSPECV_FLDENV) (UNSPECV_FNSTSW, UNSPECV_FNCLEX): New unspecs. (fnstenv, fldenv, fnstsw, fnclex): New insns. Index: gcc/config/i386/i386.md =================================================================== --- gcc/config/i386/i386.md (revision 204335) +++ gcc/config/i386/i386.md (working copy) @@ -222,6 +222,12 @@ UNSPECV_XSAVEOPT UNSPECV_XSAVEOPT64 + ;; For atomic compound assignments. + UNSPECV_FNSTENV + UNSPECV_FLDENV + UNSPECV_FNSTSW + UNSPECV_FNCLEX + ;; For RDRAND support UNSPECV_RDRAND @@ -18014,6 +18020,71 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; +;; Floating-point instructions for atomic compound assignments +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; Clobber all floating-point registers on environment save and restore +; to ensure that the TOS value saved at fnstenv is valid after fldenv. +(define_insn "fnstenv" + [(set (match_operand:BLK 0 "memory_operand" "=m") + (unspec_volatile:BLK [(const_int 0)] UNSPECV_FNSTENV)) + (clobber (reg:HI FPCR_REG)) + (clobber (reg:XF ST0_REG)) + (clobber (reg:XF ST1_REG)) + (clobber (reg:XF ST2_REG)) + (clobber (reg:XF ST3_REG)) + (clobber (reg:XF ST4_REG)) + (clobber (reg:XF ST5_REG)) + (clobber (reg:XF ST6_REG)) + (clobber (reg:XF ST7_REG))] + "TARGET_80387" + "fnstenv\t%0" + [(set_attr "type" "other") + (set_attr "memory" "store") + (set (attr "length") + (symbol_ref "ix86_attr_length_address_default (insn) + 2"))]) + +(define_insn "fldenv" + [(unspec_volatile [(match_operand:BLK 0 "memory_operand" "m")] + UNSPECV_FLDENV) + (clobber (reg:CCFP FPSR_REG)) + (clobber (reg:HI FPCR_REG)) + (clobber (reg:XF ST0_REG)) + (clobber (reg:XF ST1_REG)) + (clobber (reg:XF ST2_REG)) + (clobber (reg:XF ST3_REG)) + (clobber (reg:XF ST4_REG)) + (clobber (reg:XF ST5_REG)) + (clobber (reg:XF ST6_REG)) + (clobber (reg:XF ST7_REG))] + "TARGET_80387" + "fldenv\t%0" + [(set_attr "type" "other") + (set_attr "memory" "load") + (set (attr "length") + (symbol_ref "ix86_attr_length_address_default (insn) + 2"))]) + +(define_insn "fnstsw" + [(set (match_operand:HI 0 "memory_operand" "=m") + (unspec_volatile:HI [(const_int 0)] UNSPECV_FNSTSW))] + "TARGET_80387" + "fnstsw\t%0" + [(set_attr "type" "other") + (set_attr "memory" "store") + (set (attr "length") + (symbol_ref "ix86_attr_length_address_default (insn) + 2"))]) + +(define_insn "fnclex" + [(unspec_volatile [(const_int 0)] UNSPECV_FNCLEX)] + "TARGET_80387" + "fnclex" + [(set_attr "type" "other") + (set_attr "memory" "none") + (set_attr "length" "2")]) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; LWP instructions ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Index: gcc/config/i386/i386-builtin-types.def =================================================================== --- gcc/config/i386/i386-builtin-types.def (revision 204335) +++ gcc/config/i386/i386-builtin-types.def (working copy) @@ -227,6 +227,7 @@ DEF_FUNCTION_TYPE (VOID, PCVOID) DEF_FUNCTION_TYPE (VOID, PVOID) DEF_FUNCTION_TYPE (VOID, UINT64) DEF_FUNCTION_TYPE (VOID, UNSIGNED) +DEF_FUNCTION_TYPE (VOID, PUSHORT) DEF_FUNCTION_TYPE (INT, PUSHORT) DEF_FUNCTION_TYPE (INT, PUNSIGNED) DEF_FUNCTION_TYPE (INT, PULONGLONG) Index: gcc/config/i386/i386.c =================================================================== --- gcc/config/i386/i386.c (revision 204335) +++ gcc/config/i386/i386.c (working copy) @@ -26818,6 +26818,11 @@ enum ix86_builtins IX86_BUILTIN_LFENCE, IX86_BUILTIN_PAUSE, + IX86_BUILTIN_FNSTENV, + IX86_BUILTIN_FLDENV, + IX86_BUILTIN_FNSTSW, + IX86_BUILTIN_FNCLEX, + IX86_BUILTIN_BSRSI, IX86_BUILTIN_BSRDI, IX86_BUILTIN_RDPMC, @@ -27794,6 +27799,12 @@ static const struct builtin_description bdesc_spec { ~OPTION_MASK_ISA_64BIT, CODE_FOR_nothing, "__builtin_ia32_rdtscp", IX86_BUILTIN_RDTSCP, UNKNOWN, (int) UINT64_FTYPE_PUNSIGNED }, { ~OPTION_MASK_ISA_64BIT, CODE_FOR_pause, "__builtin_ia32_pause", IX86_BUILTIN_PAUSE, UNKNOWN, (int) VOID_FTYPE_VOID }, + /* 80387 (for use internally for atomic compound assignment). */ + { 0, CODE_FOR_fnstenv, "__builtin_ia32_fnstenv", IX86_BUILTIN_FNSTENV, UNKNOWN, (int) VOID_FTYPE_PVOID }, + { 0, CODE_FOR_fldenv, "__builtin_ia32_fldenv", IX86_BUILTIN_FLDENV, UNKNOWN, (int) VOID_FTYPE_PCVOID }, + { 0, CODE_FOR_fnstsw, "__builtin_ia32_fnstsw", IX86_BUILTIN_FNSTSW, UNKNOWN, (int) VOID_FTYPE_PUSHORT }, + { 0, CODE_FOR_fnclex, "__builtin_ia32_fnclex", IX86_BUILTIN_FNCLEX, UNKNOWN, (int) VOID_FTYPE_VOID }, + /* MMX */ { OPTION_MASK_ISA_MMX, CODE_FOR_mmx_emms, "__builtin_ia32_emms", IX86_BUILTIN_EMMS, UNKNOWN, (int) VOID_FTYPE_VOID }, @@ -32751,6 +32762,10 @@ ix86_expand_builtin (tree exp, rtx target, rtx sub case IX86_BUILTIN_FXRSTOR: case IX86_BUILTIN_FXSAVE64: case IX86_BUILTIN_FXRSTOR64: + case IX86_BUILTIN_FNSTENV: + case IX86_BUILTIN_FLDENV: + case IX86_BUILTIN_FNSTSW: + mode0 = BLKmode; switch (fcode) { case IX86_BUILTIN_FXSAVE: @@ -32765,6 +32780,16 @@ ix86_expand_builtin (tree exp, rtx target, rtx sub case IX86_BUILTIN_FXRSTOR64: icode = CODE_FOR_fxrstor64; break; + case IX86_BUILTIN_FNSTENV: + icode = CODE_FOR_fnstenv; + break; + case IX86_BUILTIN_FLDENV: + icode = CODE_FOR_fldenv; + break; + case IX86_BUILTIN_FNSTSW: + icode = CODE_FOR_fnstsw; + mode0 = HImode; + break; default: gcc_unreachable (); } @@ -32777,7 +32802,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx sub op0 = convert_memory_address (Pmode, op0); op0 = copy_addr_to_reg (op0); } - op0 = gen_rtx_MEM (BLKmode, op0); + op0 = gen_rtx_MEM (mode0, op0); pat = GEN_FCN (icode) (op0); if (pat) @@ -43385,7 +43410,34 @@ ix86_atomic_assign_expand_fenv (tree *hold, tree * tree exceptions_var = create_tmp_var (integer_type_node, NULL); if (TARGET_80387) { - /* TODO */ + tree fenv_index_type = build_index_type (size_int (6)); + tree fenv_type = build_array_type (unsigned_type_node, fenv_index_type); + tree fenv_var = create_tmp_var (fenv_type, NULL); + mark_addressable (fenv_var); + tree fenv_ptr = build_pointer_type (fenv_type); + tree fenv_addr = build1 (ADDR_EXPR, fenv_ptr, fenv_var); + fenv_addr = fold_convert (ptr_type_node, fenv_addr); + tree fnstenv = ix86_builtins[IX86_BUILTIN_FNSTENV]; + tree fldenv = ix86_builtins[IX86_BUILTIN_FLDENV]; + tree fnstsw = ix86_builtins[IX86_BUILTIN_FNSTSW]; + tree fnclex = ix86_builtins[IX86_BUILTIN_FNCLEX]; + tree hold_fnstenv = build_call_expr (fnstenv, 1, fenv_addr); + tree hold_fnclex = build_call_expr (fnclex, 0); + *hold = build2 (COMPOUND_EXPR, void_type_node, hold_fnstenv, + hold_fnclex); + *clear = build_call_expr (fnclex, 0); + tree sw_var = create_tmp_var (short_unsigned_type_node, NULL); + mark_addressable (sw_var); + tree su_ptr = build_pointer_type (short_unsigned_type_node); + tree sw_addr = build1 (ADDR_EXPR, su_ptr, sw_var); + tree fnstsw_call = build_call_expr (fnstsw, 1, sw_addr); + tree exceptions_x87 = fold_convert (integer_type_node, sw_var); + tree update_mod = build2 (MODIFY_EXPR, integer_type_node, + exceptions_var, exceptions_x87); + *update = build2 (COMPOUND_EXPR, integer_type_node, + fnstsw_call, update_mod); + tree update_fldenv = build_call_expr (fldenv, 1, fenv_addr); + *update = build2 (COMPOUND_EXPR, void_type_node, *update, update_fldenv); } if (TARGET_SSE_MATH) { -- Joseph S. Myers jos...@codesourcery.com