From: Eikansh Gupta Date: Tue, 31 Mar 2026 11:21:00 +0000 (+0530) Subject: tree-ssa-dce: eliminate dead relaxed atomic loads with no LHS [PR123966] X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f1b16d7a17bf2cd8f5071e94384a0893c124e7bf;p=thirdparty%2Fgcc.git tree-ssa-dce: eliminate dead relaxed atomic loads with no LHS [PR123966] A relaxed atomic load whose result is never used has no observable effect: the value is discarded and __ATOMIC_RELAXED provides no inter-thread synchronisation guarantee. Fix this by adding an early-return check for BUILT_IN_ATOMIC_LOAD_1/2/4/8/16 calls that have no LHS and a compile-time-constant relaxed memory order. PR tree-optimization/123966 gcc/ChangeLog: * tree-ssa-dce.cc (mark_stmt_if_obviously_necessary): Don't mark a relaxed atomic load with no LHS as necessary. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/pr123966.c: New test. Signed-off-by: Eikansh Gupta --- diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr123966.c b/gcc/testsuite/gcc.dg/tree-ssa/pr123966.c new file mode 100644 index 00000000000..7658f1d1945 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr123966.c @@ -0,0 +1,71 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-cddce1" } */ + +unsigned char g1; +unsigned short g2; +unsigned int g4; +unsigned long long g8; + +/* Relaxed loads, result unused -- must be eliminated. */ +void test_relaxed_1 (void) +{ + unsigned char r; + __atomic_load (&g1, &r, 0); +} + +void test_relaxed_2 (void) +{ + unsigned short r; + __atomic_load (&g2, &r, 0); +} + +void test_relaxed_4 (void) +{ + unsigned int r; + __atomic_load (&g4, &r, 0); +} + +void test_relaxed_8 (void) +{ + unsigned long long r; + __atomic_load (&g8, &r, 0); +} + +/* Non-relaxed orders, result unused -- must be preserved. */ +void test_acquire (void) +{ + unsigned int r; + __atomic_load (&g4, &r, 2); +} + +void test_seqcst (void) +{ + unsigned int r; + __atomic_load (&g4, &r, 5); +} + +void test_consume (void) +{ + unsigned int r; + __atomic_load (&g4, &r, 1); +} + +/* Runtime order -- must be preserved (order unknown at compile time). */ +void test_runtime (int order) +{ + unsigned int r; + __atomic_load (&g4, &r, order); +} + +/* Relaxed load but result is used -- must be preserved. */ +unsigned int test_used (void) +{ + unsigned int r; + __atomic_load (&g4, &r, 0); + return r; +} + +/* { dg-final { scan-tree-dump-times "__atomic_load_1" 0 "cddce1" } } */ +/* { dg-final { scan-tree-dump-times "__atomic_load_2" 0 "cddce1" } } */ +/* { dg-final { scan-tree-dump-times "__atomic_load_8" 0 "cddce1" } } */ +/* { dg-final { scan-tree-dump-times "__atomic_load_4" 5 "cddce1" } } */ diff --git a/gcc/tree-ssa-dce.cc b/gcc/tree-ssa-dce.cc index 7932607e889..bc8ae6d10f9 100644 --- a/gcc/tree-ssa-dce.cc +++ b/gcc/tree-ssa-dce.cc @@ -70,6 +70,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-ssa.h" #include "ipa-modref-tree.h" #include "ipa-modref.h" +#include "memmodel.h" static struct stmt_stats { @@ -408,6 +409,29 @@ mark_stmt_if_obviously_necessary (gimple *stmt, bool aggressive) if (is_removable_cxa_atexit_call (call)) return; + /* A relaxed atomic load with no LHS has no observable effect: + the value is discarded and relaxed ordering provides no + inter-thread synchronisation guarantee. Don't mark it + necessary so DCE can remove it. */ + if (gimple_call_builtin_p (call, BUILT_IN_NORMAL)) + switch (DECL_FUNCTION_CODE (gimple_call_fndecl (call))) + { + case BUILT_IN_ATOMIC_LOAD_1: + case BUILT_IN_ATOMIC_LOAD_2: + case BUILT_IN_ATOMIC_LOAD_4: + case BUILT_IN_ATOMIC_LOAD_8: + case BUILT_IN_ATOMIC_LOAD_16: + { + tree model_arg = gimple_call_arg (call, 1); + if (TREE_CODE (model_arg) == INTEGER_CST + && is_mm_relaxed (memmodel_from_int (tree_to_uhwi (model_arg)))) + return; + break; + } + default: + break; + } + /* IFN_GOACC_LOOP calls are necessary in that they are used to represent parameter (i.e. step, bound) of a lowered OpenACC partitioned loop. But this kind of partitioned loop might not