On 2018-08-11 6:17 PM, John David Anglin wrote:
It recently came to my attention that PA 2.0 supports out-of-order
execution for loads and
stores. Loads and stores are strongly ordered on PA 1.x. This has
caused no end of confusion.
This out-of-order execution is discussed in the following article:
http://web.archive.org/web/20040214092531/http://www.cpus.hp.com/technical_references/advperf.shtml
This patch defines a new barrier pattern to enforce ordering of memory
accesses.
The existing atomic patterns have been removed from pa.md except for
atomic_loaddi and atomic_storedi
which use floating point double instructions. The defaults are okay
when combined with the new barrier.
Since we want PA 1.x code to be PA 2.0 compatible, it gets the barrier
as well.
The linux atomic support is modified to use the new barrier in the
lock release code. This should improve
performance.
Tested on hppa-unknown-linux-gnu. Committed to trunk. Probably, I
will backport the change once the
change receives more testing.
This patch partially reverts the above change. I should not have
removed the integer atomic store patterns.
We need to use the kernel compare and swap helper for atomic stores on
linux as the compare and swap
operation is synthesized and a store in the middle of this operation can
be lost. It should occur either
before or after the operation.
Tested on hppa-unknown-linux-gnu. Committed to active branches.
Dave
--
John David Anglin dave.ang...@bell.net
2018-09-19 John David Anglin <dang...@gcc.gnu.org>
* config/pa/pa.md (atomic_storeqi): Restore deleted expander.
(atomic_storehi): Likewise.
(atomic_storesi): Likewise.
(atomic_loaddi): Restore compare and swap exchange loop code.
Index: config/pa/pa.md
===================================================================
--- config/pa/pa.md (revision 264413)
+++ config/pa/pa.md (working copy)
@@ -9958,8 +9958,60 @@
;; These patterns are at the bottom so the non atomic versions are preferred.
-;; Implement atomic DImode load using 64-bit floating point load.
+(define_expand "atomic_storeqi"
+ [(match_operand:QI 0 "memory_operand") ;; memory
+ (match_operand:QI 1 "register_operand") ;; val out
+ (match_operand:SI 2 "const_int_operand")] ;; model
+ ""
+{
+ if (TARGET_SYNC_LIBCALL)
+ {
+ rtx mem = operands[0];
+ rtx val = operands[1];
+ if (pa_maybe_emit_compare_and_swap_exchange_loop (NULL_RTX, mem, val))
+ DONE;
+ }
+ FAIL;
+})
+;; Implement atomic HImode stores using exchange.
+
+(define_expand "atomic_storehi"
+ [(match_operand:HI 0 "memory_operand") ;; memory
+ (match_operand:HI 1 "register_operand") ;; val out
+ (match_operand:SI 2 "const_int_operand")] ;; model
+ ""
+{
+ if (TARGET_SYNC_LIBCALL)
+ {
+ rtx mem = operands[0];
+ rtx val = operands[1];
+ if (pa_maybe_emit_compare_and_swap_exchange_loop (NULL_RTX, mem, val))
+ DONE;
+ }
+ FAIL;
+})
+
+;; Implement atomic SImode store using exchange.
+
+(define_expand "atomic_storesi"
+ [(match_operand:SI 0 "memory_operand") ;; memory
+ (match_operand:SI 1 "register_operand") ;; val out
+ (match_operand:SI 2 "const_int_operand")] ;; model
+ ""
+{
+ if (TARGET_SYNC_LIBCALL)
+ {
+ rtx mem = operands[0];
+ rtx val = operands[1];
+ if (pa_maybe_emit_compare_and_swap_exchange_loop (NULL_RTX, mem, val))
+ DONE;
+ }
+ FAIL;
+})
+
+;; Implement atomic DImode load.
+
(define_expand "atomic_loaddi"
[(match_operand:DI 0 "register_operand") ;; val out
(match_operand:DI 1 "memory_operand") ;; memory
@@ -9999,6 +10051,14 @@
{
enum memmodel model;
+ if (TARGET_SYNC_LIBCALL)
+ {
+ rtx mem = operands[0];
+ rtx val = operands[1];
+ if (pa_maybe_emit_compare_and_swap_exchange_loop (NULL_RTX, mem, val))
+ DONE;
+ }
+
if (TARGET_64BIT || TARGET_DISABLE_FPREGS || TARGET_SOFT_FLOAT)
FAIL;