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).