[PATCH v2 6/7] Alpha: Add option to avoid data races for sub-longword memory stores [PR117759]
Jeff Law
jeffreyalaw@gmail.com
Tue Jan 7 04:20:33 GMT 2025
On 1/6/25 6:03 AM, Maciej W. Rozycki wrote:
> With non-BWX Alpha implementations we have a problem of data races where
> a 8-bit byte or 16-bit word quantity is to be written to memory in that
> in those cases we use an unprotected RMW access of a 32-bit longword or
> 64-bit quadword width. If contents of the longword or quadword accessed
> outside the byte or word to be written are changed midway through by a
> concurrent write executing on the same CPU such as by a signal handler
> or a parallel write executing on another CPU such as by another thread
> or via a shared memory segment, then the concluding write of the RMW
> access will clobber them. This is especially important for the safety
> of RCU algorithms, but is otherwise an issue anyway.
>
> To guard against these data races with byte and aligned word quantities
> introduce the `-msafe-bwa' command-line option (standing for Safe Byte &
> Word Access) that instructs the compiler to instead use an atomic RMW
> access sequence where byte and word memory access machine instructions
> are not available. There is no change to code produced for BWX targets.
>
> It would be sufficient for the secondary reload handle to use a pair of
> scratch registers, as requested by `reload_out<mode>', but it would end
> with poor code produced as one of the scratches would be occupied by
> data retrieved and the other one would have to be reloaded with repeated
> calculations, all within the LL/SC sequence.
>
> Therefore I chose to add a dedicated `reload_out<mode>_safe_bwa' handler
> and ask for more scratches there by defining a 256-bit OI integer mode.
> While reload is documented in our manual to support an arbitrary number
> of scratches in reality it hasn't been implemented for IRA:
>
> /* ??? It would be useful to be able to handle only two, or more than
> three, operands, but for now we can only handle the case of having
> exactly three: output, input and one temp/scratch. */
>
> and it seems to be the case for LRA as well. Do what everyone else does
> then and just have one wide multi-register scratch.
>
> I note that the atomic sequences emitted are suboptimal performance-wise
> as the looping branch for the unsuccessful completion of the sequence
> points backwards, which means it will be predicted as taken despite that
> in most cases it will fall through. I do not see it as a deficiency of
> this change proposed as it takes care of recording that the branch is
> unlikely to be taken, by calling `alpha_emit_unlikely_jump'. Therefore
> generic code elsewhere shou
Looks like this got truncated. Anyway, easy to forget how limited
branch prediction was in this era. I haven't pondered static branch
prediction in forever. I wouldn't worry too much about this case -- we
can always come back to it if generic doesn't do the right thing with
code layout.
>
> Add test cases accordingly.
>
> There are notable regressions between a plain `-mno-bwx' configuration
> and a `-mno-bwx -msafe-bwa' one:
>
> FAIL: gcc.dg/torture/inline-mem-cpy-cmp-1.c -O0 execution test
> FAIL: gcc.dg/torture/inline-mem-cpy-cmp-1.c -O1 execution test
> FAIL: gcc.dg/torture/inline-mem-cpy-cmp-1.c -O2 execution test
> FAIL: gcc.dg/torture/inline-mem-cpy-cmp-1.c -O3 -g execution test
> FAIL: gcc.dg/torture/inline-mem-cpy-cmp-1.c -Os execution test
> FAIL: gcc.dg/torture/inline-mem-cpy-cmp-1.c -O2 -flto -fno-use-linker-plugin -flto-partition=none execution test
> FAIL: gcc.dg/torture/inline-mem-cpy-cmp-1.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects execution test
> FAIL: g++.dg/init/array25.C -std=c++17 execution test
> FAIL: g++.dg/init/array25.C -std=c++98 execution test
> FAIL: g++.dg/init/array25.C -std=c++26 execution test
>
> They come from the fact that these test cases play tricks with alignment
> and end up calling code that expects a reference to aligned data but is
> handed one to unaligned data.
>
> This doesn't cause a visible problem with plain `-mno-bwx' code, because
> the resulting alignment exception is fixed up by Linux. There's no such
> handling currently implemented for LDL_L or LDQ_L instructions (which
> are first in the sequence) and consequently the offender is issued with
> SIGBUS instead. Suitable handling will be added to Linux to complement
> this change, so these regressions are seen as harmless and expected.
>
> gcc/
> PR target/117759
> * config/alpha/alpha-modes.def (OI): New integer mode.
> * config/alpha/alpha-protos.h (alpha_expand_mov_safe_bwa): New
> prototype.
> * config/alpha/alpha.cc (alpha_expand_mov_safe_bwa): New
> function.
> (alpha_secondary_reload): Handle TARGET_SAFE_BWA.
> * config/alpha/alpha.md (aligned_store_safe_bwa)
> (unaligned_store<mode>_safe_bwa, reload_out<mode>_safe_bwa)
> (reload_out<mode>_unaligned_safe_bwa): New expanders.
> (mov<mode>, movcqi, reload_out<mode>_aligned): Handle
> TARGET_SAFE_BWA.
> (reload_out<mode>): Guard against TARGET_SAFE_BWA.
> * config/alpha/alpha.opt (msafe-bwa): New option.
> * config/alpha/alpha.opt.urls: Regenerate.
> * doc/invoke.texi (Option Summary, DEC Alpha Options): Document
> the new option.
>
> gcc/testsuite/
> PR target/117759
> * gcc.target/alpha/stb.c: New file.
> * gcc.target/alpha/stb-bwa.c: New file.
> * gcc.target/alpha/stb-bwx.c: New file.
> * gcc.target/alpha/stba.c: New file.
> * gcc.target/alpha/stba-bwa.c: New file.
> * gcc.target/alpha/stba-bwx.c: New file.
> * gcc.target/alpha/stw.c: New file.
> * gcc.target/alpha/stw-bwa.c: New file.
> * gcc.target/alpha/stw-bwx.c: New file.
> * gcc.target/alpha/stwa.c: New file.
> * gcc.target/alpha/stwa-bwa.c: New file.
> * gcc.target/alpha/stwa-bwx.c: New file.
> ---
> NB I note that there is a warning in gcc/config/alpha/sync.md that it is
> unpredictable if the lock_flag is cleared or not by a normal load or store
> executed on the same CPU and therefore we need to make sure no register
> spill is inserted in the sequence. I seem not to have seen it actually
> happen and testing results with actual hardware do look good.
If it's a real issue in practice and we have to revisit this code, then
we could look at hard barriers before/after the sequence to prevent
scheduling into the sequence. Or we could emit the entire sequence as
an atomic unit much like some ports do for inlined subword atomics.
>
> However out of the abundance of caution we may want to make sure it can't
> happen. It should be quite a straightforward change, but owing to the
> number of issues encountered, as indicated by the size of the patchset,
> and the limited time I did not get to it in time for Stage 1 closure. So
> I've chosen to post this change for review anyway with the intent to make
> a suitable update in the coming weeks. As it only affects newly-added
> `-msafe-bwa' option I don't think it will be disruptive to the pre-release
> stabilisation process. I will appreciate input for this part
>
> NB2 I reckon the manual ought to be updated to say only one scratch is
> permitted for secondary reloads. While it's documented otherwise since
> forever, it's never actually matched reality.
ISTM that could be a follow-up. Consider such an update pre-approved.
OK for the trunk.
jeff
More information about the Gcc-patches
mailing list