From patchwork Wed Sep 2 09:01:28 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Biener X-Patchwork-Id: 142692 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id EBB8D4BA2E14 for ; Wed, 2 Sep 2026 09:03:29 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org EBB8D4BA2E14 Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=suse.de header.i=@suse.de header.a=rsa-sha256 header.s=susede2_rsa header.b=qD9U9FDG; dkim=pass header.d=suse.de header.i=@suse.de header.a=ed25519-sha256 header.s=susede2_ed25519 header.b=+k3Z1Bgn; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.a=rsa-sha256 header.s=susede2_rsa header.b=Ik3BjZaf; dkim=neutral header.d=suse.de header.i=@suse.de header.a=ed25519-sha256 header.s=susede2_ed25519 header.b=3po40/eJ X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from smtp-out1.suse.de (smtp-out1.suse.de [IPv6:2a07:de40:b251:101:10:150:64:1]) by sourceware.org (Postfix) with ESMTPS id AC6B14BA79AC for ; Wed, 2 Sep 2026 09:01:39 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org AC6B14BA79AC Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=suse.de ARC-Filter: OpenARC Filter v1.0.0 sourceware.org AC6B14BA79AC Authentication-Results: sourceware.org; arc=none smtp.remote-ip=2a07:de40:b251:101:10:150:64:1 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1788339699; cv=none; b=J91BNEm0X7VuHig+r9tLPM8MB67KMA0s2XypP3Jow3A32hlNbjnhHJzMKIRk1i4f+r9S7Oicv8ynmsZOgVghGDJBoi4/0mfLSjt4rq3oVJkf6CbNtlcBqa0GaFN7uWJQTv59DFhRW+PBFwZoa2wNFXyE1W7WZmX4RlP9kgfh5S0= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1788339699; c=relaxed/simple; bh=x2JuILfFdMkyZqggMblXsQNSNapidMuPnlxd3STexkQ=; h=DKIM-Signature:DKIM-Signature:DKIM-Signature:DKIM-Signature:Date: From:To:Subject:Message-ID:MIME-Version; b=QA6+VGz48DS9cLcFa71w1XlLvYhA0fL70MzlaTo/rBcQyqsJrUciql4XysZjnxrnVT/EiuhX/2TPzLmHtSknThmm0yXrUCrfZOZPSNs/dz4iAV8JniW7XQcXRD619wbxjnJLEhpQgYlpi6dxMW7ovyPcrJ9uik1ZDa94+xeK/ho= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=suse.de header.i=@suse.de header.a=rsa-sha256 header.s=susede2_rsa header.b=qD9U9FDG; dkim=pass header.d=suse.de header.i=@suse.de header.a=ed25519-sha256 header.s=susede2_ed25519 header.b=+k3Z1Bgn; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.a=rsa-sha256 header.s=susede2_rsa header.b=Ik3BjZaf; dkim=neutral header.d=suse.de header.i=@suse.de header.a=ed25519-sha256 header.s=susede2_ed25519 header.b=3po40/eJ DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org AC6B14BA79AC Received: from murzim.nue2.suse.org (unknown [10.168.4.243]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id BA76421FAC; Wed, 2 Sep 2026 09:01:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1788339692; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=aTVCNOsAY2ZPfo6l4TQ6PpGHNAHScScfloJsmfAl410=; b=qD9U9FDG58gpvDDCA8Wxpx6thoACW0AUVysxB3tIjlwMHim7V0NmOthL08Eu1wxTL5peQG d1zBctVwuV+XZkS69CzTWICkukp2lJAj84MhUcnoDXCN25YIL7npPyT/SUHIAtGlDePafe teaAfImFLv5f7X/DUqXWzi5Z84D6Sa4= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1788339692; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=aTVCNOsAY2ZPfo6l4TQ6PpGHNAHScScfloJsmfAl410=; b=+k3Z1Bgn0MfuUMmN5N+Qd5KASB4LzNQyMj+XvBl0G3lwZwuZgWsoo4adZcKhAEz1G7lfvm 2Pd+fgTdmA+yKKAg== Authentication-Results: smtp-out1.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1788339688; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=aTVCNOsAY2ZPfo6l4TQ6PpGHNAHScScfloJsmfAl410=; b=Ik3BjZafYQW0PyGwR7zp0XBY4m2UtmGd8w+LAIArIwpo5kPcPtmBmvbPqxIdF5yZNz9UyO fatLQONZ0WUNrGxLMNMFDomNcxNRlir6/ILqs/UI6GtfS8sCeqtAzHEqRng7eL3kBVm3VM +sn8c7n0mvj9ItsPj4hKsApo7UUMmfY= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1788339688; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=aTVCNOsAY2ZPfo6l4TQ6PpGHNAHScScfloJsmfAl410=; b=3po40/eJDCmM5SgpBQeQ31OorqF5UBUQlJkgYqRnwBYGkTMxWe1vJdCp6IHTnHEhL32ml/ zwh3LNgnxlhvSxDw== Date: Wed, 2 Sep 2026 11:01:28 +0200 (CEST) From: Richard Biener To: gcc-patches@gcc.gnu.org cc: ebotcazou@adacore.com Subject: [PATCH] tree-optimization: do not lose reverse storage order when translating a ref Message-ID: MIME-Version: 1.0 X-Spam-Level: X-Spam-Score: -4.30 X-Spamd-Result: default: False [-4.30 / 50.00]; BAYES_HAM(-3.00)[100.00%]; NEURAL_HAM_LONG(-1.00)[-1.000]; NEURAL_HAM_SHORT(-0.20)[-0.998]; MIME_GOOD(-0.10)[text/plain]; RCVD_COUNT_ZERO(0.00)[0]; ARC_NA(0.00)[]; MISSING_XM_UA(0.00)[]; RCPT_COUNT_TWO(0.00)[2]; FROM_HAS_DN(0.00)[]; DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; URIBL_BLOCKED(0.00)[tree-ssa-sccvn.cc:url,fhfr.qr:mid,murzim.nue2.suse.org:helo,anthropic.com:email]; FROM_EQ_ENVFROM(0.00)[]; MIME_TRACE(0.00)[0:+]; TO_DN_NONE(0.00)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[murzim.nue2.suse.org:helo, tree-ssa-sccvn.cc:url, fhfr.qr:mid, anthropic.com:email] X-Spam-Status: No, score=-11.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_PASS, TXREP shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org When vn_reference_lookup_3 translates a reference through an aggregate copy it may fail to find a common base and instead reduce the lookup to the base of the copy's right-hand side plus a constant offset, folding all of the original operands away. A reversed storage order is a property of the component and not of its position, so it cannot be recovered from that offset: the translated reference ends up in natural order and the later "assignment from a constant" case interprets the stored bytes with the wrong bit numbering, silently producing a wrong value. Punt in that case, i.e. when no original operand survives and either access is in reverse storage order. When an operand does survive it stays outermost and carries the flag, so the storage order of the translated reference is unchanged; a reverse flag on an inner operand only describes an inner container and does not affect the byte order of the scalar access. reverse_storage_order_for_component_p now takes its argument by const reference so that the auto_vec holding the right-hand side operands can be passed to it. Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. Eric, is the SSO use sound for the testcase (which was LLM generated)? Thanks, Richard. * tree-ssa-sccvn.cc (reverse_storage_order_for_component_p): Take the operands by const reference. (vn_reference_lookup_3): Punt when translating a reference through an aggregate copy consumes all of its operands and either access has reverse storage order. * gcc.dg/torture/sso-fre-1.c: New test. Co-Authored-By: Claude Opus 5 --- gcc/testsuite/gcc.dg/torture/sso-fre-1.c | 43 ++++++++++++++++++++++++ gcc/tree-ssa-sccvn.cc | 13 ++++++- 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/torture/sso-fre-1.c diff --git a/gcc/testsuite/gcc.dg/torture/sso-fre-1.c b/gcc/testsuite/gcc.dg/torture/sso-fre-1.c new file mode 100644 index 00000000000..2862517f838 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/sso-fre-1.c @@ -0,0 +1,43 @@ +/* { dg-do run } */ +/* { dg-require-effective-target le } */ + +/* Value numbering used to translate a reference through an aggregate copy + by folding the components of the reference into a constant offset into + the right-hand side of the copy. A reversed storage order is a property + of the component and not of its position, so it was lost in the process + and the load of F7 below was resolved to the least significant bits of + the byte instead of to its most significant bits. */ + +struct __attribute__((scalar_storage_order("big-endian"))) S0 +{ + signed f7 : 3; + unsigned f6 : 5; +}; + +struct S1 { int a; struct S0 f3; char pad; short s; }; + +struct S1 g; +struct S1 *escape; + +__attribute__((noipa)) int +foo (void) +{ + struct S1 l; + struct S0 *q; + + /* Reversed bit order, so this gives f7 == 1 and f6 == 4. */ + *(char *) &g.f3 = 0x24; + l = g; + /* Keep L addressable so that it is not scalarized away. */ + escape = &l; + q = (struct S0 *) ((char *) &l + __builtin_offsetof (struct S1, f3)); + return q->f7; +} + +int +main (void) +{ + if (foo () != 1) + __builtin_abort (); + return 0; +} diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc index dbb19e4a498..95b5642ba36 100644 --- a/gcc/tree-ssa-sccvn.cc +++ b/gcc/tree-ssa-sccvn.cc @@ -1727,7 +1727,7 @@ contains_storage_order_barrier_p (vec ops) /* Return true if OPS represent an access with reverse storage order. */ static bool -reverse_storage_order_for_component_p (vec ops) +reverse_storage_order_for_component_p (const vec &ops) { unsigned i = 0; if (ops[i].opcode == REALPART_EXPR || ops[i].opcode == IMAGPART_EXPR) @@ -3779,6 +3779,17 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, tree rhs1 = gimple_assign_rhs1 (def_stmt); copy_reference_ops_from_ref (rhs1, &rhs); + /* When none of the original operands survives the storage order of + the translated reference is the one of the RHS of the copy. The + operands we folded into a constant offset above may well have + specified a reverse storage order, which is a property of the + component and not of its position, so it is not recoverable from + that offset. Punt unless both accesses are in natural order. */ + if (i < 0 + && (reverse_storage_order_for_component_p (vr->operands) + || reverse_storage_order_for_component_p (rhs))) + return (void *)-1; + /* Apply an extra offset to the inner MEM_REF of the RHS. */ bool force_no_tbaa = false; if (maybe_ne (extra_off, 0))