GCC provides its own version of stdatomic.h since GCC 4.9. Here we have: #define atomic_load_explicit(PTR, MO) \ __extension__ \ ({ \ __auto_type __atomic_load_ptr = (PTR); \ __typeof__ (*__atomic_load_ptr) __atomic_load_tmp; \ __atomic_load (__atomic_load_ptr, &__atomic_load_tmp, (MO)); \ __atomic_load_tmp; \ })
According to http://en.cppreference.com/w/c/atomic/atomic_load (or in the standard "7.17.7.2 The atomic_load generic functions") we have C atomic_load_explicit( volatile A* obj, memory_order order ); This test case #include <stdatomic.h> int ld(volatile atomic_int *i) { return atomic_load_explicit(i, memory_order_relaxed); } yields on ARM arm-rtems4.11-gcc -march=armv7-a -O2 test.c -S && cat test.s .arch armv7-a .fpu softvfp .eabi_attribute 20, 1 .eabi_attribute 21, 1 .eabi_attribute 23, 3 .eabi_attribute 24, 1 .eabi_attribute 25, 1 .eabi_attribute 26, 1 .eabi_attribute 30, 2 .eabi_attribute 34, 1 .eabi_attribute 18, 4 .file "test.c" .text .align 2 .global ld .type ld, %function ld: @ args = 0, pretend = 0, frame = 8 @ frame_needed = 0, uses_anonymous_args = 0 @ link register save eliminated. ldr r3, [r0] sub sp, sp, #8 str r3, [sp, #4] ldr r0, [sp, #4] add sp, sp, #8 @ sp needed bx lr .size ld, .-ld .ident "GCC: (GNU) 4.9.1 20140515 (prerelease) To solve this performance issue discard all qualifiers in __typeof__ and __auto_type for atomic types. With this patch we have rm-rtems4.11-gcc -march=armv7-a -O2 test.c -S && cat test.s .arch armv7-a .fpu softvfp .eabi_attribute 20, 1 .eabi_attribute 21, 1 .eabi_attribute 23, 3 .eabi_attribute 24, 1 .eabi_attribute 25, 1 .eabi_attribute 26, 1 .eabi_attribute 30, 2 .eabi_attribute 34, 1 .eabi_attribute 18, 4 .file "test.c" .text .align 2 .global ld .type ld, %function ld: @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 @ link register save eliminated. ldr r0, [r0] bx lr .size ld, .-ld .ident "GCC: (GNU) 4.9.1 20140625 (prerelease) gcc/c/ChangeLog 2014-06-25 Sebastian Huber <sebastian.hu...@embedded-brains.de> * c-parser.c (c_parser_declaration_or_fndef): Discard all type qualifiers in __auto_type for atomic types. (c_parser_typeof_specifier): Discard all type qualifiers in __typeof__ for atomic types. --- gcc/c/c-parser.c | 21 ++++++--------------- 1 files changed, 6 insertions(+), 15 deletions(-) diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 99ff546..037da03 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -1707,14 +1707,10 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, " initializer"); init = convert_lvalue_to_rvalue (init_loc, init, true, true); tree init_type = TREE_TYPE (init.value); - /* As with typeof, remove _Atomic and const - qualifiers from atomic types. */ + /* As with typeof, remove all qualifiers from atomic types. */ if (init_type != error_mark_node && TYPE_ATOMIC (init_type)) init_type - = c_build_qualified_type (init_type, - (TYPE_QUALS (init_type) - & ~(TYPE_QUAL_ATOMIC - | TYPE_QUAL_CONST))); + = c_build_qualified_type (init_type, TYPE_UNQUALIFIED); bool vm_type = variably_modified_type_p (init_type, NULL_TREE); if (vm_type) @@ -3011,16 +3007,11 @@ c_parser_typeof_specifier (c_parser *parser) if (was_vm) ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands); pop_maybe_used (was_vm); - /* For use in macros such as those in <stdatomic.h>, remove - _Atomic and const qualifiers from atomic types. (Possibly - all qualifiers should be removed; const can be an issue for - more macros using typeof than just the <stdatomic.h> - ones.) */ + /* For use in macros such as those in <stdatomic.h>, remove all + qualifiers from atomic types. (const can be an issue for more macros + using typeof than just the <stdatomic.h> ones.) */ if (ret.spec != error_mark_node && TYPE_ATOMIC (ret.spec)) - ret.spec = c_build_qualified_type (ret.spec, - (TYPE_QUALS (ret.spec) - & ~(TYPE_QUAL_ATOMIC - | TYPE_QUAL_CONST))); + ret.spec = c_build_qualified_type (ret.spec, TYPE_UNQUALIFIED); } c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); return ret; -- 1.7.7