https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92692
Bug ID: 92692 Summary: Saving off the callee saved register between ldxr/stxr (caused by shrink wrapping improvements) Product: gcc Version: 10.0 Status: UNCONFIRMED Keywords: wrong-code Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: pinskia at gcc dot gnu.org Target Milestone: --- Target: aarch64-linux-gnu Created attachment 47375 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=47375&action=edit compile at -O2 This was originally reported at https://sourceware.org/bugzilla/show_bug.cgi?id=24924 but it turns out the issue is a gcc issue and a glibc issue. The UNSPECV_ATOMIC_CMPSW: (insn 177 176 1270 17 (parallel [ (set (reg:CC 66 cc) (unspec_volatile:CC [ (const_int 0 [0]) ] UNSPECV_ATOMIC_CMPSW)) (set (reg:SI 8 x8 [251]) (mem/v:SI (reg/f:DI 16 x16 [orig:346 _41 ] [346]) [-1 S4 A32])) (set (mem/v:SI (reg/f:DI 16 x16 [orig:346 _41 ] [346]) [-1 S4 A32]) (unspec_volatile:SI [ (reg:SI 1 x1 [orig:117 _42 ] [117]) (reg:SI 5 x5 [249]) (const_int 1 [0x1]) (const_int 2 [0x2]) (const_int 0 [0]) ] UNSPECV_ATOMIC_CMPSW)) (clobber (reg:SI 19 x19 [363])) ]) "pthread_rwlock_common.c":687:135 3712 {aarch64_compare_and_swapsi} (nil)) Is split (after register allocator/reload) into: (insn 1580 176 1581 17 (set (reg:SI 8 x8 [251]) (unspec_volatile:SI [ (mem/v:SI (reg/f:DI 16 x16 [orig:346 _41 ] [346]) [-1 S4 A32]) (const_int 2 [0x2]) ] UNSPECV_LX)) "pthread_rwlock_common.c":687:135 3842 {aarch64_load_exclusivesi} (nil)) (insn 1581 1580 1582 17 (set (reg:CC 66 cc) (compare:CC (reg:SI 8 x8 [251]) (reg:SI 1 x1 [orig:117 _42 ] [117]))) "pthread_rwlock_common.c":687:135 447 {cmpsi} (nil)) (jump_insn 1582 1581 1616 17 (set (pc) (if_then_else (ne (reg:CC 66 cc) (const_int 0 [0])) (label_ref:DI 1585) (pc))) "pthread_rwlock_common.c":687:135 9 {condjump} (int_list:REG_BR_PROB 536868 (nil)) -> 1585) ... (insn 1583 1616 1584 99 (parallel [ (set (reg:SI 19 x19 [363]) (unspec_volatile:SI [ (const_int 0 [0]) ] UNSPECV_SX)) (set (mem/v:SI (reg/f:DI 16 x16 [orig:346 _41 ] [346]) [-1 S4 A32]) (unspec_volatile:SI [ (reg:SI 5 x5 [249]) (const_int 2 [0x2]) ] UNSPECV_SX)) ]) "pthread_rwlock_common.c":687:135 3847 {aarch64_store_exclusivesi} (nil)) (insn 1584 1583 1585 99 (set (reg:CC 66 cc) (compare:CC (reg:SI 19 x19 [363]) (const_int 0 [0]))) "pthread_rwlock_common.c":687:135 447 {cmpsi} (nil)) Which is ok, but notice the register x19. It is a callee saved register but it is only used in the UNSPECV_SX/compare. After .pro_and_epilogue: We get for the UNSPECV_SX/compare: (insn/f 1659 1616 1583 25 (set (mem/c:DI (plus:DI (reg/f:DI 31 sp) (const_int 16 [0x10])) [38 S8 A8]) (reg:DI 19 x19)) -1 (expr_list:REG_CFA_OFFSET (set (mem/c:DI (plus:DI (reg/f:DI 31 sp) (const_int 16 [0x10])) [38 S8 A8]) (reg:DI 19 x19)) (nil))) (insn 1583 1659 1584 25 (parallel [ (set (reg:SI 19 x19 [363]) (unspec_volatile:SI [ (const_int 0 [0]) ] UNSPECV_SX)) (set (mem/v:SI (reg/f:DI 16 x16 [orig:346 _41 ] [346]) [-1 S4 A32]) (unspec_volatile:SI [ (reg:SI 5 x5 [249]) (const_int 2 [0x2]) ] UNSPECV_SX)) ]) "pthread_rwlock_common.c":687:135 3847 {aarch64_store_exclusivesi} (nil)) (insn 1584 1583 1661 25 (set (reg:CC 66 cc) (compare:CC (reg:SI 19 x19 [363]) (const_int 0 [0]))) "pthread_rwlock_common.c":687:135 447 {cmpsi} (nil)) (insn/f 1661 1584 1585 25 (set (reg:DI 19 x19) (mem/c:DI (plus:DI (reg/f:DI 31 sp) (const_int 16 [0x10])) [38 S8 A8])) "pthread_rwlock_common.c":687:135 -1 (expr_list:REG_CFA_RESTORE (reg:DI 19 x19) (nil))) ---- CUT --- This causes UNSPECV_SX to always fail on a few AARCH64 targets (ThunderX1/OcteonTX1 and OcteonTX2).