Fix wrong-code issues of RX atomic operations.
authorOleg Endo <olegendo@gcc.gnu.org>
Tue, 31 May 2016 15:06:25 +0000 (15:06 +0000)
committerOleg Endo <olegendo@gcc.gnu.org>
Tue, 31 May 2016 15:06:25 +0000 (15:06 +0000)
gcc/
* config/rx/rx.md (FETCHOP_NO_MINUS): New code iterator.
(atomic_<fetchop_name>_fetchsi): Extract minus operator into ...
(atomic_sub_fetchsi): ... this new pattern.
(mvtc): Add CC_REG clobber.

From-SVN: r236926

gcc/ChangeLog
gcc/config/rx/rx.md

index 59aae29bdc410537460d363bc8010487ab965d47..bdc3d172c4ed55adb19d9bf452b267ee1b1a6fcb 100644 (file)
@@ -1,3 +1,10 @@
+2016-05-31  Oleg Endo  <olegendo@gcc.gnu.org>
+
+       * config/rx/rx.md (FETCHOP_NO_MINUS): New code iterator.
+       (atomic_<fetchop_name>_fetchsi): Extract minus operator into ...
+       (atomic_sub_fetchsi): ... this new pattern.
+       (mvtc): Add CC_REG clobber.
+
 2016-05-31  Marek Polacek  <polacek@redhat.com>
 
        * gimplify.c (gimplify_switch_expr): Also handle GIMPLE_TRY.
index 9af16828b8cb29142895d2597613f3c727fa5180..b63f17708cec5e786493e1f66c75a77c456b70c0 100644 (file)
 ;; Atomic operations.
 
 (define_code_iterator FETCHOP [plus minus ior xor and])
+(define_code_iterator FETCHOP_NO_MINUS [plus ior xor and])
 
 (define_code_attr fetchop_name
   [(plus "add") (minus "sub") (ior "or") (xor "xor") (and "and")])
 })
 
 ;; read - modify - write - return new value
+;; Because subtraction is not commutative we need to specify a different
+;; set of patterns for it.
 (define_expand "atomic_<fetchop_name>_fetchsi"
   [(set (match_operand:SI 0 "register_operand")
-       (FETCHOP:SI (match_operand:SI 1 "rx_restricted_mem_operand")
-                   (match_operand:SI 2 "register_operand")))
+       (FETCHOP_NO_MINUS:SI (match_operand:SI 1 "rx_restricted_mem_operand")
+                            (match_operand:SI 2 "register_operand")))
    (set (match_dup 1)
-       (FETCHOP:SI (match_dup 1) (match_dup 2)))
+       (FETCHOP_NO_MINUS:SI (match_dup 1) (match_dup 2)))
    (match_operand:SI 3 "const_int_operand")]           ;; memory model
   ""
 {
   DONE;
 })
 
+(define_expand "atomic_sub_fetchsi"
+  [(set (match_operand:SI 0 "register_operand")
+       (minus:SI (match_operand:SI 1 "rx_restricted_mem_operand")
+                 (match_operand:SI 2 "rx_source_operand")))
+   (set (match_dup 1)
+       (minus:SI (match_dup 1) (match_dup 2)))
+   (match_operand:SI 3 "const_int_operand")]           ;; memory model
+  ""
+{
+  {
+    rx_atomic_sequence seq (current_function_decl);
+
+    emit_move_insn (operands[0], operands[1]);
+    emit_insn (gen_subsi3 (operands[0], operands[0], operands[2]));
+    emit_move_insn (operands[1], operands[0]);
+  }
+  DONE;
+})
+
 (define_expand "atomic_nand_fetchsi"
   [(set (match_operand:SI 0 "register_operand")
        (not:SI (and:SI (match_operand:SI 1 "rx_restricted_mem_operand")
 )
 
 ;; Move to control register
+;; This insn can be used in atomic sequences to restore the previous PSW
+;; and re-enable interrupts.  Because of that it always clobbers the CC_REG.
 (define_insn "mvtc"
   [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i,i")
               (match_operand:SI 1 "nonmemory_operand" "r,i")]
-             UNSPEC_BUILTIN_MVTC)]
+             UNSPEC_BUILTIN_MVTC)
+   (clobber (reg:CC CC_REG))]
   ""
   "mvtc\t%1, %C0"
   [(set_attr "length" "3,7")]
-  ;; Ignore possible clobbering of the comparison flags in the
-  ;; PSW register.  This is a cc0 target so any cc0 setting
-  ;; instruction will always be paired with a cc0 user, without
-  ;; the possibility of this instruction being placed in between
-  ;; them.
 )
 
 ;; Move to interrupt priority level