https://gcc.gnu.org/g:b6bebf2a7326e6b5566f1aa2979233a60e5c8377
commit r17-2556-gb6bebf2a7326e6b5566f1aa2979233a60e5c8377 Author: Shreya Munnangi <[email protected]> Date: Mon Jul 20 07:02:48 2026 -0600 [PATCH][RISC-V][PR target/124741] Improving atomic sequences In PR 124741, we have a testcase: typedef struct { int x; unsigned repr; } atomic_u_t; unsigned atomic_load_u (const atomic_u_t *a) { unsigned result; __atomic_load (&a->repr, &result, 0); return result; } When compiled with rv64, it outputs: addi a5,a0,4 lw a0,0(a5) sext.w a0,a0 ret Here we have a redundant sign extension and inefficient address arithmetic. This can be simplified into two instructions, a load and a return. The lw insn is already doing a sign extension from 32 to 64 bits, making the separate sext.w unnecessary. Adding a copy of the pattern that explicitly shows the sign extension in the RTL, with the modes adjusted accordingly, no longer emits the sext.w insn. I also generalized the pattern to support both sign and zero extension. These changes have been reflected on the total store ordering memory consistency model as well. As Zalrsc doesn't support zero extending load-acquire instructions, I introduced a new iterator, ensuring zero extend is limited to !TARGET_ZALRSC for load. The addi and lw are combined into lw a0,4(a5) by adjusting the memory operand constraint to handle offsets in the load patterns. The validity of the memory operand constraint depends on the value of operand 2 - the memory model. I introduced new constraint alternatives, such that the behavior of the memory operand constraint is triggered on whether the memory model acquire is being used or not and the Zalrsc or non-Zalrsc targets accordingly. Similar changes were made for the store patterns where the inefficient address arithmetic problem was also present. PR target/124741 gcc/ * config/riscv/constraints.md (B1, B2, B3, B4): New constraints for atomic loads with and without ZALASR & MEMMODEL_ACQUIRE. * config/riscv/iterators.md (cond_extend): New iterator to for use in extending atomic loads. * config/riscv/sync-rvwmo.md (atomic_load_rvwmo<mode>): Adjust contraints to enable folding small offsets into memory load. (atomic_store_rvwmo): Likewise. (extending atomic_load_rvwmo): New pattern. * config/riscv/sync-ztso.md (atomic_load_ztso<mode>): Adjust constraints to enable folding small offsets into memory load. (atomic_store_ztso): Likewise. (extending atomic_load_ztso): New pattern. gcc/testsuite/ * gcc.target/riscv/load-zalasr.c: Testcases for atomic load compiled with rv64 and zalasr ext. * gcc.target/riscv/load.c: Testcases for atomic load compiled with rv64. * gcc.target/riscv/load32-zalasr.c: Testcases for atomic load compiled with rv32 and zalasr ext. * gcc.target/riscv/load32.c: Testcases for atomic load compiled with rv32. * gcc.target/riscv/store-zalasr.c: Testcases for atomic store compiled with rv64 and zalasr ext. * gcc.target/riscv/store.c: Testcases for atomic store compiled with rv64. * gcc.target/riscv/store32-zalasr.c: Testcases for atomic store compiled with rv32 and zalasr ext. * gcc.target/riscv/store32.c: Testcases for atomic store compiled with rv32. Co-authored-by: Jeff Law <[email protected]> Diff: --- gcc/config/riscv/constraints.md | 26 +++ gcc/config/riscv/iterators.md | 3 + gcc/config/riscv/sync-rvwmo.md | 43 ++++- gcc/config/riscv/sync-ztso.md | 31 +++- gcc/testsuite/gcc.target/riscv/load-zalasr.c | 201 ++++++++++++++++++++++++ gcc/testsuite/gcc.target/riscv/load.c | 197 +++++++++++++++++++++++ gcc/testsuite/gcc.target/riscv/load32-zalasr.c | 161 +++++++++++++++++++ gcc/testsuite/gcc.target/riscv/load32.c | 157 ++++++++++++++++++ gcc/testsuite/gcc.target/riscv/store-zalasr.c | 122 ++++++++++++++ gcc/testsuite/gcc.target/riscv/store.c | 122 ++++++++++++++ gcc/testsuite/gcc.target/riscv/store32-zalasr.c | 105 +++++++++++++ gcc/testsuite/gcc.target/riscv/store32.c | 106 +++++++++++++ 12 files changed, 1263 insertions(+), 11 deletions(-) diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md index 8051c1e330b1..d9fc9704ef57 100644 --- a/gcc/config/riscv/constraints.md +++ b/gcc/config/riscv/constraints.md @@ -145,6 +145,32 @@ (and (match_code "mem") (match_test "GET_CODE(XEXP(op,0)) == REG"))) +(define_constraint "B1" + "Memory models that can match with A for load." + (and (match_code "const_int") + (and (match_test "ival == MEMMODEL_ACQUIRE") + (match_test "TARGET_ZALASR")))) + +(define_constraint "B2" + "Memory models that can match with m for load." + (and (match_code "const_int") + (ior (match_test "ival != MEMMODEL_ACQUIRE") + (match_test "!TARGET_ZALASR")))) + +(define_constraint "B3" + "Memory models that can match with A for store." + (and (match_code "const_int") + (and (ior (match_test "ival == MEMMODEL_RELEASE") + (match_test "ival == MEMMODEL_SEQ_CST")) + (match_test "TARGET_ZALASR")))) + +(define_constraint "B4" + "Memory models that can match with m for store." + (and (match_code "const_int") + (ior (and (match_test "ival != MEMMODEL_RELEASE") + (match_test "ival != MEMMODEL_SEQ_CST")) + (match_test "!TARGET_ZALASR")))) + (define_constraint "S" "A constraint that matches an absolute symbolic address." (match_operand 0 "absolute_symbolic_operand")) diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md index 076911e5e7f1..dc25dfd2e99d 100644 --- a/gcc/config/riscv/iterators.md +++ b/gcc/config/riscv/iterators.md @@ -207,6 +207,9 @@ ;; This code iterator allows signed and unsigned widening multiplications ;; to use the same template. (define_code_iterator any_extend [sign_extend zero_extend]) + +(define_code_iterator cond_extend [sign_extend (zero_extend "!TARGET_ZALASR")]) + (define_code_attr extend_name [ (sign_extend "extend") (zero_extend "zero_extend") ]) diff --git a/gcc/config/riscv/sync-rvwmo.md b/gcc/config/riscv/sync-rvwmo.md index 3d4093888376..5519f2ac015d 100644 --- a/gcc/config/riscv/sync-rvwmo.md +++ b/gcc/config/riscv/sync-rvwmo.md @@ -47,10 +47,10 @@ ;; Atomic memory operations. (define_insn "atomic_load_rvwmo<mode>" - [(set (match_operand:ANYI 0 "register_operand" "=r") + [(set (match_operand:ANYI 0 "register_operand" "=r,r") (unspec_volatile:ANYI - [(match_operand:ANYI 1 "memory_operand" "A") - (match_operand:SI 2 "const_int_operand")] ;; model + [(match_operand:ANYI 1 "memory_operand" "m,A") + (match_operand:SI 2 "const_int_operand" "B2,B1")] UNSPECV_ATOMIC_LOAD))] "!TARGET_ZTSO" { @@ -74,13 +74,43 @@ : is_mm_acquire (memmodel_from_int (INTVAL (operands[2]))) ? 8 : 4)"))]) +(define_insn "atomic_load_rvwmo<X:mode><SUBX:mode><code>" + [(set (match_operand:X 0 "register_operand" "=r,r") + (cond_extend:X + (unspec_volatile:SUBX + [(match_operand:SUBX 1 "memory_operand" "m,A") + (match_operand:SUBX 2 "const_int_operand" "B2,B1")] + UNSPECV_ATOMIC_LOAD)))] + "!TARGET_ZTSO" + { + enum memmodel model = (enum memmodel) INTVAL (operands[2]); + model = memmodel_base (model); + + if (model == MEMMODEL_SEQ_CST) + return "fence\trw,rw\;" + "<SUBX:load><u>\t%0,%1\;" + "fence\tr,rw"; + if (TARGET_ZALASR && model == MEMMODEL_ACQUIRE) + return "<SUBX:load><u>.aq\t%0,%1"; + if (model == MEMMODEL_ACQUIRE) + return "<SUBX:load><u>\t%0,%1\;" + "fence\tr,rw"; + else + return "<SUBX:load><u>\t%0,%1"; + } + [(set_attr "type" "multi") + (set (attr "length") + (symbol_ref "(is_mm_seq_cst (memmodel_from_int (INTVAL (operands[2]))) ? 12 + : is_mm_acquire (memmodel_from_int (INTVAL (operands[2]))) ? 8 + : 4)"))]) + ;; Implement atomic stores with conservative fences. ;; This allows us to be compatible with the ISA manual Table A.6 and Table A.7. (define_insn "atomic_store_rvwmo<mode>" - [(set (match_operand:ANYI 0 "memory_operand" "=A") + [(set (match_operand:ANYI 0 "memory_operand" "=m,A") (unspec_volatile:ANYI - [(match_operand:ANYI 1 "reg_or_0_operand" "rJ") - (match_operand:SI 2 "const_int_operand")] ;; model + [(match_operand:ANYI 1 "reg_or_0_operand" "rJ,rJ") + (match_operand:SI 2 "const_int_operand" "B4,B3")] UNSPECV_ATOMIC_STORE))] "!TARGET_ZTSO" { @@ -90,7 +120,6 @@ if (TARGET_ZALASR && (model == MEMMODEL_RELEASE || model == MEMMODEL_SEQ_CST)) return "<store>.rl\t%z1,%0"; - if (model == MEMMODEL_SEQ_CST) return "fence\trw,w\;" "<store>\t%z1,%0\;" diff --git a/gcc/config/riscv/sync-ztso.md b/gcc/config/riscv/sync-ztso.md index 9bdd9e291d92..154ff1a91af4 100644 --- a/gcc/config/riscv/sync-ztso.md +++ b/gcc/config/riscv/sync-ztso.md @@ -43,7 +43,7 @@ (define_insn "atomic_load_ztso<mode>" [(set (match_operand:ANYI 0 "register_operand" "=r") (unspec_volatile:ANYI - [(match_operand:ANYI 1 "memory_operand" "A") + [(match_operand:ANYI 1 "memory_operand" "m") (match_operand:SI 2 "const_int_operand")] ;; model UNSPECV_ATOMIC_LOAD))] "TARGET_ZTSO" @@ -64,12 +64,35 @@ (symbol_ref "(is_mm_seq_cst (memmodel_from_int (INTVAL (operands[2]))) ? 8 : 4)"))]) +(define_insn "atomic_load_ztso<X:mode><SUBX:mode><code>" + [(set (match_operand:X 0 "register_operand" "=r") + (any_extend:X + (unspec_volatile:SUBX + [(match_operand:SUBX 1 "memory_operand" "m") + (match_operand:SUBX 2 "const_int_operand")] + UNSPECV_ATOMIC_LOAD)))] + "TARGET_ZTSO" + { + enum memmodel model = (enum memmodel) INTVAL (operands[2]); + model = memmodel_base (model); + + if (model == MEMMODEL_SEQ_CST) + return "fence\trw,rw\;" + "<SUBX:load><u>\t%0,%1"; + else + return "<SUBX:load><u>\t%0,%1"; + } + [(set_attr "type" "multi") + (set (attr "length") + (symbol_ref "(is_mm_seq_cst (memmodel_from_int (INTVAL (operands[2]))) ? 8 + : 4)"))]) + (define_insn "atomic_store_ztso<mode>" - [(set (match_operand:ANYI 0 "memory_operand" "=A") + [(set (match_operand:ANYI 0 "memory_operand" "=m,A") (unspec_volatile:ANYI - [(match_operand:ANYI 1 "reg_or_0_operand" "rJ") - (match_operand:SI 2 "const_int_operand")] ;; model + [(match_operand:ANYI 1 "reg_or_0_operand" "rJ,rJ") + (match_operand:SI 2 "const_int_operand" "B4,B3")] ;; model UNSPECV_ATOMIC_STORE))] "TARGET_ZTSO" { diff --git a/gcc/testsuite/gcc.target/riscv/load-zalasr.c b/gcc/testsuite/gcc.target/riscv/load-zalasr.c new file mode 100644 index 000000000000..10638b8a738b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/load-zalasr.c @@ -0,0 +1,201 @@ +/* { dg-do compile { target rv64 } } */ +/* { dg-options "-march=rv64gc_zalasr -mabi=lp64d" } */ +/* { dg-final { check-function-bodies "**" "" } } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Og" "-Oz" } } */ + + +typedef struct +{ + char pad; + unsigned char repr; +} qi_zero_t; + +typedef struct +{ + char pad; + signed char repr; +} qi_sign_t; + +typedef struct +{ + short pad; + unsigned short repr; +} hi_zero_t; + +typedef struct +{ + short pad; + short repr; +} hi_sign_t; + +typedef struct +{ + int pad; + int repr; +} si_sign_t; + +typedef struct +{ + int pad; + unsigned repr; +} si_zero_t; + + + +/* +**atomic_load_qi_zero: +** lb [a-z][0-9]+,1\([a-z][0-9]+\) +** andi [a-z][0-9]+,[a-z][0-9]+,0xff +** ret +*/ +unsigned atomic_load_qi_zero (const qi_zero_t *a) { + unsigned char r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_qi_sign: +** lb [a-z][0-9]+,1\([a-z][0-9]+\) +** ret +*/ +int atomic_load_qi_sign (const qi_sign_t *a) { + signed char r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_hi_zero: +** lh [a-z][0-9]+,2\([a-z][0-9]+\) +** slli [a-z][0-9]+,[a-z][0-9]+,48 +** srli [a-z][0-9]+,[a-z][0-9]+,48 +** ret +*/ +unsigned atomic_load_hi_zero (const hi_zero_t *a) { + unsigned short r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_hi_sign: +** lh [a-z][0-9]+,2\([a-z][0-9]+\) +** ret +*/ +int atomic_load_hi_sign (const hi_sign_t *a) { + short r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_si_sign: +** lw [a-z][0-9]+,4\([a-z][0-9]+\) +** ret +*/ +int atomic_load_si_sign (const si_sign_t *a) { + int r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_si_zero: +** lw [a-z][0-9]+,4\([a-z][0-9]+\) +** ret +*/ +unsigned atomic_load_si_zero (const si_zero_t *a) { + unsigned r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + + +typedef struct +{ + int pad; + unsigned long long repr; +} di_t; + +typedef struct +{ + int pad; + unsigned char repr; +} qi_di_t; + + +/* +**atomic_load_di: +** ld [a-z][0-9]+,8\([a-z][0-9]+\) +** ret +*/ +unsigned long long atomic_load_di (const di_t *a) { + unsigned long long r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_qi_di: +** lb [a-z][0-9]+,4\([a-z][0-9]+\) +** andi [a-z][0-9]+,[a-z][0-9]+,0xff +** ret +*/ +unsigned long long atomic_load_qi_di (const qi_di_t *a) { + unsigned char r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +typedef struct +{ + int pad; + unsigned repr; +} t; + + +/* +**atomic_load_relaxed: +** lw [a-z][0-9]+,4\([a-z][0-9]+\) +** ret +*/ +unsigned atomic_load_relaxed (const t *a) { + unsigned r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_acquire: +** addi [a-z][0-9]+,[a-z][0-9]+,4 +** lw.aq [a-z][0-9]+,0\([a-z][0-9]+\) +** ret +*/ +unsigned atomic_load_acquire (const t *a) { + unsigned r; + __atomic_load (&a->repr, &r, __ATOMIC_ACQUIRE); + return r; +} + +/* +**atomic_load_seqcst: +** fence rw,rw +** lw [a-z][0-9]+,4\([a-z][0-9]+\) +** fence r,rw +** ret +*/ +unsigned atomic_load_seqcst (const t *a) { + unsigned r; + __atomic_load (&a->repr, &r, __ATOMIC_SEQ_CST); + return r; +} diff --git a/gcc/testsuite/gcc.target/riscv/load.c b/gcc/testsuite/gcc.target/riscv/load.c new file mode 100644 index 000000000000..8a917888203e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/load.c @@ -0,0 +1,197 @@ +/* { dg-do compile { target rv64 } } */ +/* { dg-options "-march=rv64gc -mabi=lp64d" } */ +/* { dg-final { check-function-bodies "**" "" } } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Og" "-Oz" } } */ + +typedef struct +{ + char pad; + unsigned char repr; +} qi_zero_t; + +typedef struct +{ + char pad; + signed char repr; +} qi_sign_t; + +typedef struct +{ + short pad; + unsigned short repr; +} hi_zero_t; + +typedef struct +{ + short pad; + short repr; +} hi_sign_t; + +typedef struct +{ + int pad; + int repr; +} si_sign_t; + +typedef struct +{ + int pad; + unsigned repr; +} si_zero_t; + + + +/* +**atomic_load_qi_zero: +** lbu [a-z][0-9]+,1\([a-z][0-9]+\) +** ret +*/ +unsigned atomic_load_qi_zero (const qi_zero_t *a) { + unsigned char r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_qi_sign: +** lb [a-z][0-9]+,1\([a-z][0-9]+\) +** ret +*/ +int atomic_load_qi_sign (const qi_sign_t *a) { + signed char r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_hi_zero: +** lhu [a-z][0-9]+,2\([a-z][0-9]+\) +** ret +*/ +unsigned atomic_load_hi_zero (const hi_zero_t *a) { + unsigned short r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_hi_sign: +** lh [a-z][0-9]+,2\([a-z][0-9]+\) +** ret +*/ +int atomic_load_hi_sign (const hi_sign_t *a) { + short r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_si_sign: +** lw [a-z][0-9]+,4\([a-z][0-9]+\) +** ret +*/ +int atomic_load_si_sign (const si_sign_t *a) { + int r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_si_zero: +** lw [a-z][0-9]+,4\([a-z][0-9]+\) +** ret +*/ +unsigned atomic_load_si_zero (const si_zero_t *a) { + unsigned r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + + +typedef struct +{ + int pad; + unsigned long long repr; +} di_t; + +typedef struct +{ + int pad; + unsigned char repr; +} qi_di_t; + + +/* +**atomic_load_di: +** ld [a-z][0-9]+,8\([a-z][0-9]+\) +** ret +*/ +unsigned long long atomic_load_di (const di_t *a) { + unsigned long long r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_qi_di: +** lbu [a-z][0-9]+,4\([a-z][0-9]+\) +** ret +*/ +unsigned long long atomic_load_qi_di (const qi_di_t *a) { + unsigned char r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +typedef struct +{ + int pad; + unsigned repr; +} t; + + +/* +**atomic_load_relaxed: +** lw [a-z][0-9]+,4\([a-z][0-9]+\) +** ret +*/ +unsigned atomic_load_relaxed (const t *a) { + unsigned r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_acquire: +** lw [a-z][0-9]+,4\([a-z][0-9]+\) +** fence r,rw +** ret +*/ +unsigned atomic_load_acquire (const t *a) { + unsigned r; + __atomic_load (&a->repr, &r, __ATOMIC_ACQUIRE); + return r; +} + + +/* +**atomic_load_seqcst: +** fence rw,rw +** lw [a-z][0-9]+,4\([a-z][0-9]+\) +** fence r,rw +** ret +*/ +unsigned atomic_load_seqcst (const t *a) { + unsigned r; + __atomic_load (&a->repr, &r, __ATOMIC_SEQ_CST); + return r; +} diff --git a/gcc/testsuite/gcc.target/riscv/load32-zalasr.c b/gcc/testsuite/gcc.target/riscv/load32-zalasr.c new file mode 100644 index 000000000000..9a3756fb66a8 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/load32-zalasr.c @@ -0,0 +1,161 @@ +/* { dg-do compile { target rv32 } } */ +/* { dg-options "-march=rv32gc_zalasr -mabi=ilp32" } */ +/* { dg-final { check-function-bodies "**" "" } } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" } } */ + +typedef struct +{ + char pad; + unsigned char repr; +} qi_zero_t; + +typedef struct +{ + char pad; + signed char repr; +} qi_sign_t; + +typedef struct +{ + short pad; + unsigned short repr; +} hi_zero_t; + +typedef struct +{ + short pad; + short repr; +} hi_sign_t; + +typedef struct +{ + int pad; + int repr; +} si_sign_t; + +typedef struct +{ + int pad; + unsigned repr; +} si_zero_t; + + +/* +**atomic_load_qi_zero: +** lb [a-z][0-9]+,1\([a-z][0-9]+\) +** andi [a-z][0-9]+,[a-z][0-9]+,0xff +** ret +*/ +unsigned atomic_load_qi_zero (const qi_zero_t *a) { + unsigned char r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_qi_sign: +** lb [a-z][0-9]+,1\([a-z][0-9]+\) +** ret +*/ +int atomic_load_qi_sign (const qi_sign_t *a) { + signed char r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_hi_zero: +** lh [a-z][0-9]+,2\([a-z][0-9]+\) +** slli [a-z][0-9]+,[a-z][0-9]+,16 +** srli [a-z][0-9]+,[a-z][0-9]+,16 +** ret +*/ +unsigned atomic_load_hi_zero (const hi_zero_t *a) { + unsigned short r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_hi_sign: +** lh [a-z][0-9]+,2\([a-z][0-9]+\) +** ret +*/ +int atomic_load_hi_sign (const hi_sign_t *a) { + short r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_si_sign: +** lw [a-z][0-9]+,4\([a-z][0-9]+\) +** ret +*/ +int atomic_load_si_sign (const si_sign_t *a) { + int r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_si_zero: +** lw [a-z][0-9]+,4\([a-z][0-9]+\) +** ret +*/ +unsigned atomic_load_si_zero (const si_zero_t *a) { + unsigned r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +typedef struct +{ + int pad; + unsigned repr; +} t; + + +/* +**atomic_load_relaxed: +** lw [a-z][0-9]+,4\([a-z][0-9]+\) +** ret +*/ +unsigned atomic_load_relaxed (const t *a) { + unsigned r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_acquire: +** addi [a-z][0-9]+,[a-z][0-9]+,4 +** lw.aq [a-z][0-9]+,0\([a-z][0-9]+\) +** ret +*/ +unsigned atomic_load_acquire (const t *a) { + unsigned r; + __atomic_load (&a->repr, &r, __ATOMIC_ACQUIRE); + return r; +} + + +/* +**atomic_load_seqcst: +** fence rw,rw +** lw [a-z][0-9]+,4\([a-z][0-9]+\) +** fence r,rw +** ret +*/ +unsigned atomic_load_seqcst (const t *a) { + unsigned r; + __atomic_load (&a->repr, &r, __ATOMIC_SEQ_CST); + return r; +} diff --git a/gcc/testsuite/gcc.target/riscv/load32.c b/gcc/testsuite/gcc.target/riscv/load32.c new file mode 100644 index 000000000000..a0729ffd3cd2 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/load32.c @@ -0,0 +1,157 @@ +/* { dg-do compile { target rv32 } } */ +/* { dg-options "-march=rv32gc -mabi=ilp32" } */ +/* { dg-final { check-function-bodies "**" "" } } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Og" "-Oz" } } */ +typedef struct +{ + char pad; + unsigned char repr; +} qi_zero_t; + +typedef struct +{ + char pad; + signed char repr; +} qi_sign_t; + +typedef struct +{ + short pad; + unsigned short repr; +} hi_zero_t; + +typedef struct +{ + short pad; + short repr; +} hi_sign_t; + +typedef struct +{ + int pad; + int repr; +} si_sign_t; + +typedef struct +{ + int pad; + unsigned repr; +} si_zero_t; + + +/* +**atomic_load_qi_zero: +** lbu [a-z][0-9]+,1\([a-z][0-9]+\) +** ret +*/ +unsigned atomic_load_qi_zero (const qi_zero_t *a) { + unsigned char r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_qi_sign: +** lb [a-z][0-9]+,1\([a-z][0-9]+\) +** ret +*/ +int atomic_load_qi_sign (const qi_sign_t *a) { + signed char r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_hi_zero: +** lhu [a-z][0-9]+,2\([a-z][0-9]+\) +** ret +*/ +unsigned atomic_load_hi_zero (const hi_zero_t *a) { + unsigned short r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_hi_sign: +** lh [a-z][0-9]+,2\([a-z][0-9]+\) +** ret +*/ +int atomic_load_hi_sign (const hi_sign_t *a) { + short r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_si_sign: +** lw [a-z][0-9]+,4\([a-z][0-9]+\) +** ret +*/ +int atomic_load_si_sign (const si_sign_t *a) { + int r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_si_zero: +** lw [a-z][0-9]+,4\([a-z][0-9]+\) +** ret +*/ +unsigned atomic_load_si_zero (const si_zero_t *a) { + unsigned r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +typedef struct +{ + int pad; + unsigned repr; +} t; + + +/* +**atomic_load_relaxed: +** lw [a-z][0-9]+,4\([a-z][0-9]+\) +** ret +*/ +unsigned atomic_load_relaxed (const t *a) { + unsigned r; + __atomic_load (&a->repr, &r, __ATOMIC_RELAXED); + return r; +} + + +/* +**atomic_load_acquire: +** lw [a-z][0-9]+,4\([a-z][0-9]+\) +** fence r,rw +** ret +*/ +unsigned atomic_load_acquire (const t *a) { + unsigned r; + __atomic_load (&a->repr, &r, __ATOMIC_ACQUIRE); + return r; +} + + +/* +**atomic_load_seqcst: +** fence rw,rw +** lw [a-z][0-9]+,4\([a-z][0-9]+\) +** fence r,rw +** ret +*/ +unsigned atomic_load_seqcst (const t *a) { + unsigned r; + __atomic_load (&a->repr, &r, __ATOMIC_SEQ_CST); + return r; +} diff --git a/gcc/testsuite/gcc.target/riscv/store-zalasr.c b/gcc/testsuite/gcc.target/riscv/store-zalasr.c new file mode 100644 index 000000000000..d2f5f0103750 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/store-zalasr.c @@ -0,0 +1,122 @@ +/* { dg-do compile { target rv64 } } */ +/* { dg-options "-march=rv64gc_zalasr -mabi=lp64d" } */ +/* { dg-final { check-function-bodies "**" "" } } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" } } */ + +typedef struct +{ + char pad; + unsigned char repr; +} qi_s_t; + +typedef struct +{ + short pad; + unsigned short repr; +} hi_s_t; + +typedef struct +{ + int pad; + unsigned repr; +} si_s_t; + + +/* +**atomic_store_qi: +** sb [a-z][0-9]+,1\([a-z][0-9]+\) +** ret +*/ +void +atomic_store_qi (qi_s_t *a, unsigned char val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_RELAXED); +} + + +/* +**atomic_store_hi: +** sh [a-z][0-9]+,2\([a-z][0-9]+\) +** ret +*/ +void +atomic_store_hi (hi_s_t *a, unsigned short val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_RELAXED); +} + + +/* +**atomic_store_si: +** sw [a-z][0-9]+,4\([a-z][0-9]+\) +** ret +*/ +void +atomic_store_si (si_s_t *a, unsigned val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_RELAXED); +} + + +typedef struct +{ + int pad; + unsigned long long repr; +} di_s_t; + + +/* +**atomic_store_di: +** sd [a-z][0-9]+,8\([a-z][0-9]+\) +** ret +*/ +void +atomic_store_di (di_s_t *a, unsigned long long val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_RELAXED); +} + + +typedef struct +{ + int pad; + unsigned repr; +} s_mm; + + +/* +**atomic_store_relaxed: +** sw [a-z][0-9]+,4\([a-z][0-9]+\) +** ret +*/ +void +atomic_store_relaxed (s_mm *a, unsigned val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_RELAXED); +} + + +/* +**atomic_store_release: +** addi [a-z][0-9]+,[a-z][0-9]+,4 +** sw.rl [a-z][0-9]+,0\([a-z][0-9]+\) +** ret +*/ +void +atomic_store_release (s_mm *a, unsigned val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_RELEASE); +} + + +/* +**atomic_store_seqcst: +** addi [a-z][0-9]+,[a-z][0-9]+,4 +** sw.rl [a-z][0-9]+,0\([a-z][0-9]+\) +** ret +*/ +void +atomic_store_seqcst (s_mm *a, unsigned val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_SEQ_CST); +} diff --git a/gcc/testsuite/gcc.target/riscv/store.c b/gcc/testsuite/gcc.target/riscv/store.c new file mode 100644 index 000000000000..d71756e92682 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/store.c @@ -0,0 +1,122 @@ +/* { dg-do compile { target rv64 } } */ +/* { dg-options "-march=rv64gc -mabi=lp64d" } */ +/* { dg-final { check-function-bodies "**" "" } } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" } } */ +typedef struct +{ + char pad; + unsigned char repr; +} qi_s_t; + +typedef struct +{ + short pad; + unsigned short repr; +} hi_s_t; + +typedef struct +{ + int pad; + unsigned repr; +} si_s_t; + + +/* +**atomic_store_qi: +** sb [a-z][0-9]+,1\([a-z][0-9]+\) +** ret +*/ +void +atomic_store_qi (qi_s_t *a, unsigned char val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_RELAXED); +} + + +/* +**atomic_store_hi: +** sh [a-z][0-9]+,2\([a-z][0-9]+\) +** ret +*/ +void +atomic_store_hi (hi_s_t *a, unsigned short val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_RELAXED); +} + + +/* +**atomic_store_si: +** sw [a-z][0-9]+,4\([a-z][0-9]+\) +** ret +*/ +void +atomic_store_si (si_s_t *a, unsigned val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_RELAXED); +} + + +typedef struct +{ + int pad; + unsigned long long repr; +} di_s_t; + + +/* +**atomic_store_di: +** sd [a-z][0-9]+,8\([a-z][0-9]+\) +** ret +*/ +void +atomic_store_di (di_s_t *a, unsigned long long val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_RELAXED); +} + + +typedef struct +{ + int pad; + unsigned repr; +} s_mm; + + +/* +**atomic_store_relaxed: +** sw [a-z][0-9]+,4\([a-z][0-9]+\) +** ret +*/ +void +atomic_store_relaxed (s_mm *a, unsigned val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_RELAXED); +} + + +/* +**atomic_store_release: +** fence rw,w +** sw [a-z][0-9]+,4\([a-z][0-9]+\) +** ret +*/ +void +atomic_store_release (s_mm *a, unsigned val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_RELEASE); +} + + +/* +**atomic_store_seqcst: +** fence rw,w +** sw [a-z][0-9]+,4\([a-z][0-9]+\) +** fence rw,rw +** ret +*/ +void +atomic_store_seqcst (s_mm *a, unsigned val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_SEQ_CST); +} diff --git a/gcc/testsuite/gcc.target/riscv/store32-zalasr.c b/gcc/testsuite/gcc.target/riscv/store32-zalasr.c new file mode 100644 index 000000000000..d4e37e7169f3 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/store32-zalasr.c @@ -0,0 +1,105 @@ +/* { dg-do compile { target rv32 } } */ +/* { dg-options "-march=rv32gc_zalasr -mabi=ilp32" } */ +/* { dg-final { check-function-bodies "**" "" } } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" } } */ + +typedef struct +{ + char pad; + unsigned char repr; +} qi_s_t; + +typedef struct +{ + short pad; + unsigned short repr; +} hi_s_t; + +typedef struct +{ + int pad; + unsigned repr; +} si_s_t; + + +/* +**atomic_store_qi: +** sb [a-z][0-9]+,1\([a-z][0-9]+\) +** ret +*/ +void +atomic_store_qi (qi_s_t *a, unsigned char val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_RELAXED); +} + + +/* +**atomic_store_hi: +** sh [a-z][0-9]+,2\([a-z][0-9]+\) +** ret +*/ +void +atomic_store_hi (hi_s_t *a, unsigned short val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_RELAXED); +} + + +/* +**atomic_store_si: +** sw [a-z][0-9]+,4\([a-z][0-9]+\) +** ret +*/ +void +atomic_store_si (si_s_t *a, unsigned val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_RELAXED); +} + + + + +typedef struct +{ + int pad; + unsigned repr; +} s_mm; + + +/* +**atomic_store_relaxed: +** sw [a-z][0-9]+,4\([a-z][0-9]+\) +** ret +*/ +void +atomic_store_relaxed (s_mm *a, unsigned val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_RELAXED); +} + + +/* +**atomic_store_release: +** addi [a-z][0-9]+,[a-z][0-9]+,4 +** sw.rl [a-z][0-9]+,0\([a-z][0-9]+\) +** ret +*/ +void +atomic_store_release (s_mm *a, unsigned val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_RELEASE); +} + + +/* +**atomic_store_seqcst: +** addi [a-z][0-9]+,[a-z][0-9]+,4 +** sw.rl [a-z][0-9]+,0\([a-z][0-9]+\) +** ret +*/ +void +atomic_store_seqcst (s_mm *a, unsigned val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_SEQ_CST); +} diff --git a/gcc/testsuite/gcc.target/riscv/store32.c b/gcc/testsuite/gcc.target/riscv/store32.c new file mode 100644 index 000000000000..7818852f9094 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/store32.c @@ -0,0 +1,106 @@ +/* { dg-do compile { target rv32 } } */ +/* { dg-options "-march=rv32gc -mabi=ilp32" } */ +/* { dg-final { check-function-bodies "**" "" } } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" } } */ + +typedef struct +{ + char pad; + unsigned char repr; +} qi_s_t; + +typedef struct +{ + short pad; + unsigned short repr; +} hi_s_t; + +typedef struct +{ + int pad; + unsigned repr; +} si_s_t; + + +/* +**atomic_store_qi: +** sb [a-z][0-9]+,1\([a-z][0-9]+\) +** ret +*/ +void +atomic_store_qi (qi_s_t *a, unsigned char val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_RELAXED); +} + + +/* +**atomic_store_hi: +** sh [a-z][0-9]+,2\([a-z][0-9]+\) +** ret +*/ +void +atomic_store_hi (hi_s_t *a, unsigned short val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_RELAXED); +} + + +/* +**atomic_store_si: +** sw [a-z][0-9]+,4\([a-z][0-9]+\) +** ret +*/ +void +atomic_store_si (si_s_t *a, unsigned val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_RELAXED); +} + + + + +typedef struct +{ + int pad; + unsigned repr; +} s_mm; + + +/* +**atomic_store_relaxed: +** sw [a-z][0-9]+,4\([a-z][0-9]+\) +** ret +*/ +void +atomic_store_relaxed (s_mm *a, unsigned val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_RELAXED); +} + + +/* +**atomic_store_release: +** fence rw,w +** sw [a-z][0-9]+,4\([a-z][0-9]+\) +** ret +*/ +void +atomic_store_release (s_mm *a, unsigned val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_RELEASE); +} + + +/* +**atomic_store_seqcst: +** fence rw,w +** sw [a-z][0-9]+,4\([a-z][0-9]+\) +** fence rw,rw +** ret +*/ +void +atomic_store_seqcst (s_mm *a, unsigned val) +{ + __atomic_store (&a->repr, &val, __ATOMIC_SEQ_CST); +}
