[PATCH ARM] Inline expansion of __sync_* builtins.

Richard Earnshaw rearnsha@arm.com
Tue Aug 10 14:08:00 GMT 2010


On Tue, 2010-08-10 at 09:46 +0100, Marcus Shawcroft wrote:
> This patch inlines builtin synchronization primitives for ARM targets that
> provide load/store exclusive.
> 
> All __sync_* builtins applied to a 32bit object will be inlined on ARM
> targets which provide the ldrex/strex instructions, primitives applied to 8
> or 16 bit objects will be inlined on targets which provide
> ldrex{b,h}/strex{b,h} in all other cases we fall back to the existing
> library functions. The __sync_synchronize() builtin will emit an inline DMB
> or MCR instruction on targets where this is appropriate.
>
> The ldrex/strex synchronization loops are represented as opaque instruction
> blobs. This provides a guarantee that no memory reference can be inserted
> between the ldrex / strex pair.
> 
> Memory references in the ldrex*/strex* instructions are always indirect, we
> do not (yet) exploit offset addressing on targets where this is available.
> 
> 2010-08-10  Marcus Shawcroft  <marcus.shawcroft@arm.com>
> 
>         * config/arm/arm-protos.h (arm_expand_sync): New.
>         (arm_output_memory_barrier, arm_output_sync_insn): New.
>         (arm_sync_loop_insns): New.
>         * config/arm/arm.c (FL_ARCH7): New.
>         (FL_FOR_ARCH7): Include FL_ARCH7.
>         (arm_arch7): New.
>         (arm_print_operand): Support %C markup.
>         (arm_legitimize_sync_memory): New.
>         (arm_emit, arm_insn_count, arm_count, arm_output_asm_insn): New.
>         (arm_process_output_memory_barrier, arm_output_memory_barrier): New.
>         (arm_ldrex_suffix, arm_output_ldrex, arm_output_strex): New.
>         (arm_output_op2, arm_output_op3, arm_output_sync_loop): New.
>         (arm_get_sync_operand, FETCH_SYNC_OPERAND): New.
>         (arm_process_output_sync_insn, arm_output_sync_insn): New.
>         (arm_sync_loop_insns,arm_call_generator, arm_expand_sync): New.
>         * config/arm/arm.h (struct arm_sync_generator): New.
>         (TARGET_HAVE_DMB, TARGET_HAVE_DMB_MCR): New.
>         (TARGET_HAVE_LDREX, TARGET_HAVE_LDREXBHD): New.
>         * config/arm/arm.md: Include sync.md.
>         (UNSPEC_MEMORY_BARRIER): New.
>         (VUNSPEC_SYNC_COMPARE_AND_SWAP, VUNSPEC_SYNC_LOCK, VUNSPEC_SYNC_OP):
> New.
>         (VUNSPEC_SYNC_NEW_OP, VUNSPEC_SYNC_OLD_OP): New.
>         (sync_result, sync_memory, sync_required_value): New attributes.
>         (sync_new_value, sync_t1, sync_t2): Likewise.
>         (sync_release_barrier, sync_op): Likewise.
>         (length): Add logic to length attribute defintion to call
>         arm_sync_loop_insns when appropriate.
>         * config/arm/sync.md: New file.
> 

+/* Emit the memory barrier instruction, if any, provided by this
+   target to a specified emitter.  */
+static void
+arm_process_output_memory_barrier (emit_f emit, rtx *operands)
+{
+  if (TARGET_HAVE_DMB)
+    {
+      /* Note we issue a system level barrier. We should consider
+         issuing a inner shareabilty zone barrier here instead, ie.
+         "DMB ISH".  */
+      emit (0, "dmb\tsy", operands);
+    }
+  else if (TARGET_HAVE_DMB_MCR)
+    emit (0, "mcr\tp15, 0, r0, c7, c10, 5", operands);
+}

I'm uncomfortable with the fact that this can fall through and not emit
a barrier in some circumstances.  Shouldn't it fall back to a library
call?  Otherwise code built for a uni-processor may fail to run on a
later multi-processor core.

Apart from this, I can't see any other problems.

R.




More information about the Gcc-patches mailing list