PR 49969 showed a mismatch between the short sync expanders and their associated insns: the former allowed zero operands but the predicates in the latter didn't.
Tested on mips64-linux-gnu and applied. Richard gcc/ PR target/49696 * config/mips/sync.md (sync_<optab>_12): Allow zero operands. (sync_old_<optab>_12, sync_new_<optab>_12, sync_nand_12): Likewise. (sync_old_nand_12, sync_new_nand_12, test_and_set_12): Likewise. gcc/testsuite/ * gcc.dg/pr49696.c: New test. Index: gcc/config/mips/sync.md =================================================================== --- gcc/config/mips/sync.md 2011-10-02 18:40:01.000000000 +0100 +++ gcc/config/mips/sync.md 2011-10-02 18:42:25.000000000 +0100 @@ -136,7 +136,7 @@ (define_insn "sync_<optab>_12" [(match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d") (atomic_hiqi_op:SI (match_dup 0) - (match_operand:SI 3 "register_operand" "dJ"))] + (match_operand:SI 3 "reg_or_0_operand" "dJ"))] UNSPEC_SYNC_OLD_OP_12)) (clobber (match_scratch:SI 4 "=&d"))] "GENERATE_LL_SC" @@ -177,7 +177,7 @@ (define_insn "sync_old_<optab>_12" [(match_operand:SI 2 "register_operand" "d") (match_operand:SI 3 "register_operand" "d") (atomic_hiqi_op:SI (match_dup 0) - (match_operand:SI 4 "register_operand" "dJ"))] + (match_operand:SI 4 "reg_or_0_operand" "dJ"))] UNSPEC_SYNC_OLD_OP_12)) (clobber (match_scratch:SI 5 "=&d"))] "GENERATE_LL_SC" @@ -218,7 +218,7 @@ (define_insn "sync_new_<optab>_12" (match_operand:SI 2 "register_operand" "d") (match_operand:SI 3 "register_operand" "d") (atomic_hiqi_op:SI (match_dup 0) - (match_operand:SI 4 "register_operand" "dJ"))] + (match_operand:SI 4 "reg_or_0_operand" "dJ"))] UNSPEC_SYNC_NEW_OP_12)) (set (match_dup 1) (unspec_volatile:SI @@ -259,7 +259,7 @@ (define_insn "sync_nand_12" [(match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d") (match_dup 0) - (match_operand:SI 3 "register_operand" "dJ")] + (match_operand:SI 3 "reg_or_0_operand" "dJ")] UNSPEC_SYNC_OLD_OP_12)) (clobber (match_scratch:SI 4 "=&d"))] "GENERATE_LL_SC" @@ -298,7 +298,7 @@ (define_insn "sync_old_nand_12" (unspec_volatile:SI [(match_operand:SI 2 "register_operand" "d") (match_operand:SI 3 "register_operand" "d") - (match_operand:SI 4 "register_operand" "dJ")] + (match_operand:SI 4 "reg_or_0_operand" "dJ")] UNSPEC_SYNC_OLD_OP_12)) (clobber (match_scratch:SI 5 "=&d"))] "GENERATE_LL_SC" @@ -337,7 +337,7 @@ (define_insn "sync_new_nand_12" [(match_operand:SI 1 "memory_operand" "+R") (match_operand:SI 2 "register_operand" "d") (match_operand:SI 3 "register_operand" "d") - (match_operand:SI 4 "register_operand" "dJ")] + (match_operand:SI 4 "reg_or_0_operand" "dJ")] UNSPEC_SYNC_NEW_OP_12)) (set (match_dup 1) (unspec_volatile:SI @@ -546,7 +546,7 @@ (define_insn "test_and_set_12" (set (match_dup 1) (unspec_volatile:SI [(match_operand:SI 2 "register_operand" "d") (match_operand:SI 3 "register_operand" "d") - (match_operand:SI 4 "arith_operand" "dJ")] + (match_operand:SI 4 "reg_or_0_operand" "dJ")] UNSPEC_SYNC_EXCHANGE_12))] "GENERATE_LL_SC" { return mips_output_sync_loop (insn, operands); } Index: gcc/testsuite/gcc.dg/pr49696.c =================================================================== --- /dev/null 2011-10-02 10:31:49.966695399 +0100 +++ gcc/testsuite/gcc.dg/pr49696.c 2011-10-02 18:42:25.000000000 +0100 @@ -0,0 +1,29 @@ +/* { dg-require-effective-target sync_char_short } */ + +/* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */ + +void +foo (short *x) +{ + __sync_val_compare_and_swap (x, 1, 0); + __sync_bool_compare_and_swap (x, 1, 0); + __sync_lock_test_and_set (x, 0); + + __sync_fetch_and_add (x, 0); + __sync_fetch_and_add (x, 0); + __sync_fetch_and_add (x, 0); + __sync_fetch_and_sub (x, 0); + __sync_fetch_and_and (x, 0); + __sync_fetch_and_or (x, 0); + __sync_fetch_and_xor (x, 0); + __sync_fetch_and_nand (x, 0); + + __sync_add_and_fetch (x, 0); + __sync_add_and_fetch (x, 0); + __sync_add_and_fetch (x, 0); + __sync_sub_and_fetch (x, 0); + __sync_and_and_fetch (x, 0); + __sync_or_and_fetch (x, 0); + __sync_xor_and_fetch (x, 0); + __sync_nand_and_fetch (x, 0); +}