]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
mips: fix unintialized operand use in sync_{old,new}_<optab>_12 [PR 125628]
authorXi Ruoyao <xry111@xry111.site>
Tue, 23 Jun 2026 14:07:34 +0000 (22:07 +0800)
committerXi Ruoyao <xry111@xry111.site>
Thu, 25 Jun 2026 08:43:50 +0000 (16:43 +0800)
In GCC, if the RTL template of define_insn has multiple elements, it's
treated as a parallel expression.  And, "in parallel" means that first
all the values used in the invidiviual side-effects are computed, and
second all the actual side-effects are performed.  So when the value of
operand 1 (the output reg) is used, it's not set yet.

When optimization is enabled, the uninitialized value is replaced with 0
and then for e.g. if atomic_hiqi_op is plus, (plus (0) (val)) is folded
to simply (val).  Now the RTL template happens to be matched by
sync_old_nand_12 (of which the RTL is written in a really inconsistent
way), causing "0 + 1 = -1".

So fix the uninitialized operand use, i.e. (match_dup 0) should be
(match_dup 1).  Also slightly alter the source of the set for the memory
in sync_new_<optab>_12 to make it clear the value in the reg and in the
memory should be same after the operation.

gcc/

PR target/125628
* config/mips/sync.md (sync_old_<optab><mode>): Fix
uninitialized operand use.
(sync_new_<optab><mode>): Fix uninitialized operand use, use the
same expression for the set source of operand 0 and 1.

gcc/config/mips/sync.md

index 1d0a977066b8e5c33e0ea694c15b1bd7bb6cbef3..beabb7fe555e25dd5b499270e9d6c6f47c59c795 100644 (file)
        (unspec_volatile:SI
           [(match_operand:SI 2 "register_operand" "d")
           (match_operand:SI 3 "register_operand" "d")
-          (atomic_hiqi_op:SI (match_dup 0)
+          (atomic_hiqi_op:SI (match_dup 1)
                              (match_operand:SI 4 "reg_or_0_operand" "dJ"))]
          UNSPEC_SYNC_OLD_OP_12))
    (clobber (match_scratch:SI 5 "=&d"))]
           [(match_operand:SI 1 "memory_operand" "+ZC")
           (match_operand:SI 2 "register_operand" "d")
           (match_operand:SI 3 "register_operand" "d")
-          (atomic_hiqi_op:SI (match_dup 0)
+          (atomic_hiqi_op:SI (match_dup 1)
                              (match_operand:SI 4 "reg_or_0_operand" "dJ"))]
          UNSPEC_SYNC_NEW_OP_12))
    (set (match_dup 1)
          [(match_dup 1)
           (match_dup 2)
           (match_dup 3)
-          (match_dup 4)] UNSPEC_SYNC_NEW_OP_12))]
+          (atomic_hiqi_op:SI (match_dup 1) (match_dup 4))]
+         UNSPEC_SYNC_NEW_OP_12))]
   "GENERATE_LL_SC"
   { return mips_output_sync_loop (insn, operands); }
   [(set_attr "sync_insn1" "<insn>")