[v4,07/10] RISCV: Weaken compare_exchange LR/SC pairs
Checks
Commit Message
Introduce the %I and %J flags for setting the .aqrl bits on LR/SC pairs
as needed.
Atomic compare and exchange ops provide success and failure memory
models. C++17 and later place no restrictions on the relative strength
of each model, so ensure we cover both by using a model that enforces
the ordering of both given models.
This change brings compare_exchange LR/SC ops in line with table A.6 of the ISA
manual.
2023-04-14 Patrick O'Neill <patrick@rivosinc.com>
* riscv.cc: Add function to get the union of two
memmodels in sync.md.
* riscv-protos.h: Likewise.
* sync.md (atomic_cas_value_strong<mode>): Remove static
.aqrl bits on SC op/.rl bits on LR op and replace with
optimized %I, %J flags.
Signed-off-by: Patrick O'Neill <patrick@rivosinc.com>
---
v3 Changelog:
* Consolidate tests in [PATCH v3 10/10]
---
gcc/config/riscv/riscv-protos.h | 3 +++
gcc/config/riscv/riscv.cc | 44 +++++++++++++++++++++++++++++++++
gcc/config/riscv/sync.md | 9 +++++--
3 files changed, 54 insertions(+), 2 deletions(-)
@@ -22,6 +22,8 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_RISCV_PROTOS_H
#define GCC_RISCV_PROTOS_H
+#include "memmodel.h"
+
/* Symbol types we understand. The order of this list must match that of
the unspec enum in riscv.md, subsequent to UNSPEC_ADDRESS_FIRST. */
enum riscv_symbol_type {
@@ -79,6 +81,7 @@ extern void riscv_reinit (void);
extern poly_uint64 riscv_regmode_natural_size (machine_mode);
extern bool riscv_v_ext_vector_mode_p (machine_mode);
extern bool riscv_shamt_matches_mask_p (int, HOST_WIDE_INT);
+extern enum memmodel riscv_union_memmodels (enum memmodel, enum memmodel);
/* Routines implemented in riscv-c.cc. */
void riscv_cpu_cpp_builtins (cpp_reader *);
@@ -4278,6 +4278,36 @@ riscv_print_operand_reloc (FILE *file, rtx op, bool hi_reloc)
fputc (')', file);
}
+/* Return the memory model that encapuslates both given models. */
+
+enum memmodel
+riscv_union_memmodels (enum memmodel model1, enum memmodel model2)
+{
+ model1 = memmodel_base (model1);
+ model2 = memmodel_base (model2);
+
+ enum memmodel weaker = model1 <= model2 ? model1: model2;
+ enum memmodel stronger = model1 > model2 ? model1: model2;
+
+ switch (stronger)
+ {
+ case MEMMODEL_SEQ_CST:
+ case MEMMODEL_ACQ_REL:
+ return stronger;
+ case MEMMODEL_RELEASE:
+ if (weaker == MEMMODEL_ACQUIRE || weaker == MEMMODEL_CONSUME)
+ return MEMMODEL_ACQ_REL;
+ else
+ return stronger;
+ case MEMMODEL_ACQUIRE:
+ case MEMMODEL_CONSUME:
+ case MEMMODEL_RELAXED:
+ return stronger;
+ default:
+ gcc_unreachable ();
+ }
+}
+
/* Return true if the .AQ suffix should be added to an AMO to implement the
acquire portion of memory model MODEL. */
@@ -4331,6 +4361,8 @@ riscv_memmodel_needs_amo_release (enum memmodel model)
'R' Print the low-part relocation associated with OP.
'C' Print the integer branch condition for comparison OP.
'A' Print the atomic operation suffix for memory model OP.
+ 'I' Print the LR suffix for memory model OP.
+ 'J' Print the SC suffix for memory model OP.
'z' Print x0 if OP is zero, otherwise print OP normally.
'i' Print i if the operand is not a register.
'S' Print shift-index of single-bit mask OP.
@@ -4500,6 +4532,18 @@ riscv_print_operand (FILE *file, rtx op, int letter)
fputs (".rl", file);
break;
+ case 'I':
+ if (model == MEMMODEL_SEQ_CST)
+ fputs (".aqrl", file);
+ else if (riscv_memmodel_needs_amo_acquire (model))
+ fputs (".aq", file);
+ break;
+
+ case 'J':
+ if (riscv_memmodel_needs_amo_release (model))
+ fputs (".rl", file);
+ break;
+
case 'i':
if (code != REG)
fputs ("i", file);
@@ -130,10 +130,15 @@
(clobber (match_scratch:GPR 6 "=&r"))]
"TARGET_ATOMIC"
{
+ enum memmodel model_success = (enum memmodel) INTVAL(operands[4]);
+ enum memmodel model_failure = (enum memmodel) INTVAL(operands[5]);
+ /* Find the union of the two memory models so we can satisfy both success
+ and failure memory models. */
+ operands[5] = GEN_INT(riscv_union_memmodels(model_success, model_failure));
return "1:\;"
- "lr.<amo>.aqrl\t%0,%1\;"
+ "lr.<amo>%I5\t%0,%1\;"
"bne\t%0,%z2,1f\;"
- "sc.<amo>.rl\t%6,%z3,%1\;"
+ "sc.<amo>%J5\t%6,%z3,%1\;"
"bnez\t%6,1b\;"
"1:";
}