This patch adds atomic test and set support for the microblaze arch. Fixes: pr118280 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118280
Test case added to testsuite/gcc.dg/atomic/atomic-pr118280.c Signed-off-by: Aayush Misra <aayush.mi...@amd.com> Signed-off-by: Neal Frager <neal.fra...@amd.com> --- gcc/ChangeLog | 6 + gcc/config/microblaze/microblaze.md | 6 +- gcc/config/microblaze/sync.md | 103 +++++++++++++++--- gcc/testsuite/ChangeLog | 5 + gcc/testsuite/gcc.dg/atomic/atomic-pr118280.c | 41 +++++++ 5 files changed, 142 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/atomic/atomic-pr118280.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 78239f08f1b..a4462c87851 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2025-07-01 Neal Frager <neal.fra...@amd.com> + + PR atomic/118280 + * microblaze.md: added atomic_test_and_set support + * microblaze/sync.md: ditto + 2025-06-30 Jeff Law <j...@ventanamicro.com> PR rtl-optimization/120242 diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md index 45c48a71e8d..387784504fc 100644 --- a/gcc/config/microblaze/microblaze.md +++ b/gcc/config/microblaze/microblaze.md @@ -43,6 +43,10 @@ (UNSPEC_TLS 106) ;; jump table (UNSPEC_SET_TEXT 107) ;; set text start (UNSPEC_TEXT 108) ;; data text relative + (UNSPECV_CAS_BOOL 201) ;; compare and swap (bool) + (UNSPECV_CAS_VAL 202) ;; compare and swap (val) + (UNSPECV_CAS_MEM 203) ;; compare and swap (mem) + (UNSPECV_ATS 204) ;; atomic test and set ]) (define_c_enum "unspec" [ @@ -79,7 +83,7 @@ ;; bshift Shift operations (define_attr "type" - "unknown,branch,jump,call,load,store,move,arith,darith,imul,idiv,icmp,multi,nop,no_delay_arith,no_delay_load,no_delay_store,no_delay_imul,no_delay_move,bshift,fadd,frsub,fmul,fdiv,fcmp,fsl,fsqrt,fcvt,trap" + "unknown,branch,jump,call,load,store,move,arith,darith,imul,idiv,icmp,multi,nop,no_delay_arith,no_delay_load,no_delay_store,no_delay_imul,no_delay_move,bshift,fadd,frsub,fmul,fdiv,fcmp,fsl,fsqrt,fcvt,trap,atomic" (const_string "unknown")) ;; Main data type used by the insn diff --git a/gcc/config/microblaze/sync.md b/gcc/config/microblaze/sync.md index db7b11e5379..ebf07eb67f5 100644 --- a/gcc/config/microblaze/sync.md +++ b/gcc/config/microblaze/sync.md @@ -18,26 +18,93 @@ ;; <http://www.gnu.org/licenses/>. (define_insn "atomic_compare_and_swapsi" - [(match_operand:SI 0 "register_operand" "=&d") ;; bool output - (match_operand:SI 1 "register_operand" "=&d") ;; val output - (match_operand:SI 2 "nonimmediate_operand" "+Q") ;; memory - (match_operand:SI 3 "register_operand" "d") ;; expected value - (match_operand:SI 4 "register_operand" "d") ;; desired value - (match_operand:SI 5 "const_int_operand" "") ;; is_weak - (match_operand:SI 6 "const_int_operand" "") ;; mod_s - (match_operand:SI 7 "const_int_operand" "") ;; mod_f + [(set (match_operand:SI 0 "register_operand" "=&d") ;; bool output + (unspec_volatile:SI + [(match_operand:SI 2 "nonimmediate_operand" "+Q") ;; memory + (match_operand:SI 3 "register_operand" "d") ;; expected value + (match_operand:SI 4 "register_operand" "d")] ;; desired value + UNSPECV_CAS_BOOL)) + (set (match_operand:SI 1 "register_operand" "=&d") ;; val output + (unspec_volatile:SI [(const_int 0)] UNSPECV_CAS_VAL)) + (set (match_dup 2) + (unspec_volatile:SI [(const_int 0)] UNSPECV_CAS_MEM)) + (match_operand:SI 5 "const_int_operand" "") ;; is_weak + (match_operand:SI 6 "const_int_operand" "") ;; mod_s + (match_operand:SI 7 "const_int_operand" "") ;; mod_f (clobber (match_scratch:SI 8 "=&d"))] "" { - output_asm_insn ("addc \tr0,r0,r0", operands); - output_asm_insn ("lwx \t%1,%y2,r0", operands); - output_asm_insn ("addic\t%8,r0,0", operands); - output_asm_insn ("bnei \t%8,.-8", operands); - output_asm_insn ("cmp \t%0,%1,%3", operands); - output_asm_insn ("bnei \t%0,.+16", operands); - output_asm_insn ("swx \t%4,%y2,r0", operands); - output_asm_insn ("addic\t%8,r0,0", operands); - output_asm_insn ("bnei \t%8,.-28", operands); - return ""; + return "add \t%0,r0,r0\n\t" + "lwx \t%1,%y2,r0\n\t" + "addic\t%8,r0,0\n\t" + "bnei \t%8,.-8\n\t" + "cmp \t%8,%1,%3\n\t" + "bnei \t%8,.+20\n\t" + "swx \t%4,%y2,r0\n\t" + "addic\t%8,r0,0\n\t" + "bnei \t%8,.-28\n\t" + "addi \t%0,r0,1"; } + [(set_attr "type" "atomic") + (set_attr "mode" "SI") + (set_attr "length" "40")] +) + +;; +;; MicroBlaze has no atomic load/store instruction pair for QImode +;; +;; Use load/store reserved word with necessary mem align,shift,mask magic +;; +(define_insn "atomic_test_and_set" + [(set (match_operand:QI 0 "register_operand" "=&d") ;; bool output + (unspec_volatile:QI + [(match_operand:QI 1 "nonimmediate_operand" "+Q") ;; memory + (match_operand:SI 2 "const_int_operand" "") ;; model + ] + UNSPECV_ATS)) + (clobber (match_scratch:SI 3 "=&d")) ; old word + (clobber (match_scratch:SI 4 "=&d")) ; tmp + (clobber (match_scratch:SI 5 "=&d")) ; aligned address + (clobber (match_scratch:SI 6 "=&d")) ; shift + (clobber (match_scratch:SI 7 "=&d")) ; mask + (clobber (match_scratch:SI 8 "=&d")) ; old value + ] + "TARGET_BARREL_SHIFT" + { + return + /* word align memory address, compute shift */ + "andi \t%5,%y1,-4\n\t" + "andi \t%6,%y1,3\n\t" + "bslli \t%6,%6,3\n\t" + + /* compute set value and mask */ + "addik \t%7,r0,1\n\t" + "bsll \t%7,%7,%6\n\t" + + /* Load and reserve word */ + "lwx \t%3,%5,r0\n\t" + "addic\t%4,r0,0\n\t" + "bnei \t%4,.-8\n\t" + + /* Compute old value */ + "and \t%8,%3,%7\n\t" + + /* Test Old Value */ + "cmp \t%4,%8,r0\n\t" + "bnei \t%4,.+20\n\t" + + /* Compute Set Word */ + "or \t%4,%3,%7\n\t" + + /* Try Reserved store */ + "swx \t%4,%5,r0\n\t" + "addic\t%4,r0,0\n\t" + "bnei \t%4,.-36\n\t" + + /* Set result */ + "bsrl \t%0,%8,%6\n\t"; + } + [(set_attr "type" "atomic") + (set_attr "mode" "QI") + (set_attr "length" "64")] ) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1e78e8679fa..d3fbb73059f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2025-07-01 Neal Frager <neal.fra...@amd.com> + + PR atomic/118280 + * gcc.dg/atomic/atomic-pr118280.c: New test. + 2025-06-30 Jeff Law <j...@ventanamicro.com> PR rtl-optimization/120242 diff --git a/gcc/testsuite/gcc.dg/atomic/atomic-pr118280.c b/gcc/testsuite/gcc.dg/atomic/atomic-pr118280.c new file mode 100644 index 00000000000..1857d14602c --- /dev/null +++ b/gcc/testsuite/gcc.dg/atomic/atomic-pr118280.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-mcpu=v10.0 -mxl-barrel-shift" { target microblaze*-*-* } } */ + +#include <stdatomic.h> +#include <stdio.h> + +atomic_flag f = ATOMIC_FLAG_INIT ; + +int main() +{ + int b = 0; + int result = 0; + + b = atomic_flag_test_and_set(&f); + if (b != 0) { + result = 1; + printf ("Expected <0> Received <%d>\n", (int)b); + } + + b = atomic_flag_test_and_set(&f); + if (b != 1) { + result = 1; + printf ("Expected <1> Received <%d>\n", (int)b); + } + + b = atomic_flag_test_and_set(&f); + if (b != 1) { + result = 1; + printf ("Expected <1> Received <%d>\n", (int)b); + } + + atomic_flag_clear(&f); + + b = atomic_flag_test_and_set(&f); + if (b != 0) { + result = 1; + printf ("Expected <0> Received <%d>\n", (int)b); + } + + return result; +} -- 2.25.1