Use plq/pstq for atomic_{load,store}<mode>
authorAaron Sawdey <acsawdey@linux.ibm.com>
Mon, 20 Apr 2020 18:01:43 +0000 (13:01 -0500)
committerAaron Sawdey <acsawdey@linux.ibm.com>
Wed, 22 Apr 2020 17:19:33 +0000 (12:19 -0500)
For future architecture with prefix instructions, always use plq/pstq
rather than lq/stq for atomic load of quadword. Then we never have to
do the doubleword swap on little endian. Before this fix, -mno-pcrel
would generate lq with the doubleword swap (which was ok) and -mpcrel
would generate plq, also with the doubleword swap, which was wrong.

2020-04-20  Aaron Sawdey  <acsawdey@linux.ibm.com>

PR target/94622
* config/rs6000/sync.md (load_quadpti): Add attr "prefixed"
if TARGET_PREFIXED.
(store_quadpti): Ditto.
(atomic_load<mode>): Do not swap doublewords if TARGET_PREFIXED as
plq will be used and doesn't need it.
(atomic_store<mode>): Ditto, for pstq.

gcc/ChangeLog
gcc/config/rs6000/sync.md

index d647ab315a672076ad649c6533d1fda04b178c2d..d4cc33e3acc6cc821e7e056c54186949f8063a87 100644 (file)
@@ -1,3 +1,13 @@
+2020-04-20  Aaron Sawdey  <acsawdey@linux.ibm.com>
+
+       PR target/94622
+       * config/rs6000/sync.md (load_quadpti): Add attr "prefixed"
+       if TARGET_PREFIXED.
+       (store_quadpti): Ditto.
+       (atomic_load<mode>): Do not swap doublewords if TARGET_PREFIXED as
+       plq will be used and doesn't need it.
+       (atomic_store<mode>): Ditto, for pstq.
+
 2020-04-22  Erick Ochoa  <erick.ochoa@theobroma-systems.com>
 
        * doc/invoke.texi: Update flags turned on by -O3.
index f27edc77b6a06eb0241e4b7e49a5cdedf4081f93..5ad88806818ffa3be096ee70eaa5be47f6598f18 100644 (file)
   [(set_attr "type" "isync")
    (set_attr "length" "12")])
 
+;; If TARGET_PREFIXED, always use plq rather than lq.
 (define_insn "load_quadpti"
   [(set (match_operand:PTI 0 "quad_int_reg_operand" "=&r")
        (unspec:PTI
   "TARGET_SYNC_TI
    && !reg_mentioned_p (operands[0], operands[1])"
   "lq %0,%1"
-  [(set_attr "type" "load")])
-
+  [(set_attr "type" "load")
+   (set (attr "prefixed") (if_then_else (match_test "TARGET_PREFIXED")
+                                       (const_string "yes")
+                                       (const_string "no")))])
+
+;; Pattern load_quadpti will always use plq for atomic TImode if
+;; TARGET_PREFIXED.  It has the correct doubleword ordering on either LE
+;; or BE, so we can just move the result into the output register and
+;; do not need to do the doubleword swap for LE.  Also this avoids any
+;; confusion about whether the lq vs plq might be used based on whether
+;; op1 has PC-relative addressing.  We could potentially allow BE to
+;; use lq because it doesn't have the doubleword ordering problem.
 (define_expand "atomic_load<mode>"
   [(set (match_operand:AINT 0 "register_operand")              ;; output
        (match_operand:AINT 1 "memory_operand"))                ;; memory
 
       emit_insn (gen_load_quadpti (pti_reg, op1));
 
-      if (WORDS_BIG_ENDIAN)
+      if (WORDS_BIG_ENDIAN || TARGET_PREFIXED)
        emit_move_insn (op0, gen_lowpart (TImode, pti_reg));
       else
        {
   DONE;
 })
 
+;; If TARGET_PREFIXED, always use pstq rather than stq.
 (define_insn "store_quadpti"
   [(set (match_operand:PTI 0 "quad_memory_operand" "=wQ")
        (unspec:PTI
         [(match_operand:PTI 1 "quad_int_reg_operand" "r")] UNSPEC_LSQ))]
   "TARGET_SYNC_TI"
   "stq %1,%0"
-  [(set_attr "type" "store")])
+  [(set_attr "type" "store")
+   (set (attr "prefixed") (if_then_else (match_test "TARGET_PREFIXED")
+                                       (const_string "yes")
+                                       (const_string "no")))])
 
+;; Pattern store_quadpti will always use pstq if TARGET_PREFIXED,
+;; so the doubleword swap is never needed in that case.
 (define_expand "atomic_store<mode>"
   [(set (match_operand:AINT 0 "memory_operand")                ;; memory
        (match_operand:AINT 1 "register_operand"))      ;; input
          operands[0] = op0 = replace_equiv_address (op0, new_addr);
        }
 
-      if (WORDS_BIG_ENDIAN)
+      if (WORDS_BIG_ENDIAN || TARGET_PREFIXED)
        emit_move_insn (pti_reg, gen_lowpart (PTImode, op1));
       else
        {