| Message ID | 20260708144633.1530935-1-ams@baylibre.com |
|---|---|
| Headers |
Return-Path: <gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org> 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 38F9D4BA2E12 for <patchwork@sourceware.org>; Wed, 8 Jul 2026 14:47:57 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 38F9D4BA2E12 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, secure) header.d=baylibre.com header.i=@baylibre.com header.a=rsa-sha256 header.s=google header.b=lPLWWiHa X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wr1-x433.google.com (mail-wr1-x433.google.com [IPv6:2a00:1450:4864:20::433]) by sourceware.org (Postfix) with ESMTPS id B37234BA543C for <gcc-patches@gcc.gnu.org>; Wed, 8 Jul 2026 14:46:46 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org B37234BA543C Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=baylibre.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org B37234BA543C Authentication-Results: sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::433 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1783522006; cv=none; b=F1kXDcaiKgGqkoBxzG3UvgkmejKVvECFTALc1hnAXdTuyE2+oATV06Qk7RTts1qwmi7lFTUwFGNK4lqk+pH7E9QO9vxTV2buyP9UofCqOt2eRqt24Ijs+b+RXVekGmHn5iHoBeX37FRD7VLYjjPaIg/5BlTt4t8e7cLJBUOt9Pk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1783522006; c=relaxed/simple; bh=Nxcs0WPlhUKaJJVIP/Jy0v3BvZUZ2FRMxvfymFkrDiU=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=voLVnOGYHPH4p7nyvGF7ufvzeQ4rOvrfqV9ytqBIVzX41WZgDkpJ3v4hKPSs6ncQWycSFVtiQFrKy+HxwN9UW50mXFzNo/qKPMY9Zdem0xlBSLFjIz7ILv81t8xf2KA2cUB1ITt+WHhSkoWEA9hst528shJ9nRzq9gvwB00+/w8= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (2048-bit key, secure) header.d=baylibre.com header.i=@baylibre.com header.a=rsa-sha256 header.s=google header.b=lPLWWiHa DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B37234BA543C Received: by mail-wr1-x433.google.com with SMTP id ffacd0b85a97d-47df43bfb07so119718f8f.1 for <gcc-patches@gcc.gnu.org>; Wed, 08 Jul 2026 07:46:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre.com; s=google; t=1783522005; x=1784126805; darn=gcc.gnu.org; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=QdAc1deLgKiReTAejBGKzE6AtdlezYUuIhXDOvEUsRo=; b=lPLWWiHahxwetnFP7VR2vZbvKIEZ0Y+gZnLk/f7En9p54AZb7ZYMTGaxP9U2555Ntb KIRhH3oYi6q34aMqqYc+zWPJT4OSmiaRX8+MlFDsTNc6YfsPwOuMLKiqRQ5q7eEMGOoU 01MtZh9nY5INaZsa681a0skQ542f9x+Rh21bB7i9+gjz5QtlU1eCssB383XYKc4X2Plg 8wS4c8f5h5QX/ZBo9ZGGpQSXd8aDhq9MutW9uTJqx4Oa98DEOuEqEpyKtEyKZ0qXPv4O DwbaVNbRRPtQjF0+5DbD81Zi+kJMvhglt1TRq1+Zzhv591JF1raEbooorKloJnft6+2r rxtg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783522005; x=1784126805; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to:content-type; bh=QdAc1deLgKiReTAejBGKzE6AtdlezYUuIhXDOvEUsRo=; b=YUJBVh2AS7eHTKSQnnVMbDT8cIokDyUIqV64dsL862NAAG3SBMBW2EuV3llFHSPQiI nxVCR7kSIcbnYw3GCVbOUQt4JwEyi2/mz+BsTp0csJDX0DNt26XAcSmzJx/NAM7MaZM2 wWpIyGMigd5L1QMIQGDLytw1FO9tb0ubPU+pj2yd5aeOhJy3v7cuqu6UExA5IzxuYBhi 8zE9Moo8lRaY3bgB+sen8Lhkd1QIabxnD2iU7TdQB58KCC/MZB4+p2x3PcEKobRNLJvN gX7bPM1yI3PZrZJchOLne1wK+I8ltkYyuHcirRWB4GQ164D/hacz45JCz5AMC72KT0nF k3Pw== X-Gm-Message-State: AOJu0YycqQqMC72l8eJXOkAOCDIZuoFrq6GxPMjuo/6kGJQ7ZoVXUFQ8 /Gkj/SMbTuoN9sEXTtjyJb93RgK/SdKQfxevNyiTDacZkqlj09Pia6vsOUVhIhK5Thp2nitDrAr p6M7C X-Gm-Gg: AfdE7clrzMVEfYQGb13CdrZ4GemIfRln7j/6OZDCCv2vIsqmC2eW92047yejmO4bCoR LU1/o5wrMFhWY/8mSUuJbKsIiWKivEVdx9QMXYd2dp+gOZc0G0sPJbF6DF3FyIiaVVszGSR4ZdP Ue/g10MXt+w7OoJeoKc7ylyQPQdbIeSxZv7GhQ5dQuDHd8fEO/vS7jRuLxF0vQnDOUrOzZBPwIj pANQy+11ocD9Yd7TSsDMtmUSiLNyO9wpICeW2o1c9Gke0tNCc1pRxuXTudNHN3y8Kqkwp9iZTfk yixuNn4G1FzqZE67zoP2Rxbu0vKnYexJXf6vQ5l/DzP0mkgKRkdJMIuFcwIUot7vT1yLJDsseg+ XHccgoo/jRKl/SMdwktgh1wgCsfUkdfqFwpQxYeLPp1e0iDoByljzS81fg3ukXm9+8Ak5zwddsK ZvSFUHoWeup8iYvmagAY6Qp3k3Cg== X-Received: by 2002:a05:6000:4012:b0:476:82c:b869 with SMTP id ffacd0b85a97d-47df076a515mr3148971f8f.35.1783522005028; Wed, 08 Jul 2026 07:46:45 -0700 (PDT) Received: from vbuild-02.baylibre ([217.13.61.132]) by smtp.googlemail.com with ESMTPSA id ffacd0b85a97d-47a9e4d83bdsm43362109f8f.13.2026.07.08.07.46.44 for <gcc-patches@gcc.gnu.org> (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Jul 2026 07:46:44 -0700 (PDT) From: Andrew Stubbs <ams@baylibre.com> To: gcc-patches@gcc.gnu.org Subject: [PATCH 0/3] Address vectors (mem:<vectype> (reg:<vectype>)) Date: Wed, 8 Jul 2026 14:46:30 +0000 Message-ID: <20260708144633.1530935-1-ams@baylibre.com> X-Mailer: git-send-email 2.54.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-5.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_NONE, 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 <gcc-patches.gcc.gnu.org> List-Unsubscribe: <https://gcc.gnu.org/mailman/options/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe> List-Archive: <https://gcc.gnu.org/pipermail/gcc-patches/> List-Post: <mailto:gcc-patches@gcc.gnu.org> List-Help: <mailto:gcc-patches-request@gcc.gnu.org?subject=help> List-Subscribe: <https://gcc.gnu.org/mailman/listinfo/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe> Errors-To: gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org |
| Series |
Address vectors (mem:<vectype> (reg:<vectype>))
|
|
Message
Andrew Stubbs
July 8, 2026, 2:46 p.m. UTC
Hi all, This patch series implements the "MEMs with address vectors" feature that I want to use in AMD GCN, and have previously discussed on gcc@. The motivation is to simplify a new back-end optimization pass I'm working on and plan to post in the coming weeks. The first patch, in this series, is the middle-end enablement and documentation changes. The second patch converts the amdgcn back-end to use the new scheme, without adding any real new features. It depends on the INSN_BASE_REG_CLASS patch I posted last week (still in review) to run correctly. The third and final patch demonstrates how I can use the new MEM to extend my machine description without writing whole new insns for the vector modes, just for them to evaluate to the same assembler code in the end. I have not yet finished testing the patches, so these might not be quite the final form, but I'm not expecting big changes to the middle-end portion. (I can self-approve the amdgcn parts, once the other is committed, but comments are welcome.) OK for mainline? (Pending test results.) Thanks Andrew Stubbs (3): rtl: Allow "(mem:<vecmode> (reg:<vecmode>))" amdgcn: Implement "(mem (reg:<vecmode>))" amdgcn: Add vector atomics gcc/config/gcn/constraints.md | 49 ++- gcc/config/gcn/gcn-protos.h | 10 +- gcc/config/gcn/gcn-valu.md | 745 ++++++++++++---------------------- gcc/config/gcn/gcn.cc | 529 +++++++++++++----------- gcc/config/gcn/gcn.h | 1 + gcc/config/gcn/gcn.md | 123 +++--- gcc/doc/rtl.texi | 8 + gcc/doc/tm.texi | 13 +- gcc/emit-rtl.cc | 30 +- gcc/explow.cc | 12 +- gcc/recog.cc | 4 +- gcc/rtl.h | 2 +- gcc/rtlanal.cc | 4 +- gcc/simplify-rtx.cc | 5 +- gcc/target.def | 13 +- gcc/targhooks.cc | 4 +- gcc/targhooks.h | 3 +- 17 files changed, 768 insertions(+), 787 deletions(-)
Comments
On 08/07/2026 15:46, Andrew Stubbs wrote: > Hi all, > > This patch series implements the "MEMs with address vectors" feature > that I want to use in AMD GCN, and have previously discussed on gcc@. > The motivation is to simplify a new back-end optimization pass I'm > working on and plan to post in the coming weeks. > > The first patch, in this series, is the middle-end enablement and > documentation changes. > > The second patch converts the amdgcn back-end to use the new scheme, > without adding any real new features. It depends on the > INSN_BASE_REG_CLASS patch I posted last week (still in review) to run > correctly. > > The third and final patch demonstrates how I can use the new MEM to > extend my machine description without writing whole new insns for the > vector modes, just for them to evaluate to the same assembler code in > the end. > > I have not yet finished testing the patches, so these might not be quite > the final form, but I'm not expecting big changes to the middle-end > portion. (I can self-approve the amdgcn parts, once the other is > committed, but comments are welcome.) > > OK for mainline? (Pending test results.) The test results have come back clean. > Thanks > > Andrew Stubbs (3): > rtl: Allow "(mem:<vecmode> (reg:<vecmode>))" > amdgcn: Implement "(mem (reg:<vecmode>))" > amdgcn: Add vector atomics > > gcc/config/gcn/constraints.md | 49 ++- > gcc/config/gcn/gcn-protos.h | 10 +- > gcc/config/gcn/gcn-valu.md | 745 ++++++++++++---------------------- > gcc/config/gcn/gcn.cc | 529 +++++++++++++----------- > gcc/config/gcn/gcn.h | 1 + > gcc/config/gcn/gcn.md | 123 +++--- > gcc/doc/rtl.texi | 8 + > gcc/doc/tm.texi | 13 +- > gcc/emit-rtl.cc | 30 +- > gcc/explow.cc | 12 +- > gcc/recog.cc | 4 +- > gcc/rtl.h | 2 +- > gcc/rtlanal.cc | 4 +- > gcc/simplify-rtx.cc | 5 +- > gcc/target.def | 13 +- > gcc/targhooks.cc | 4 +- > gcc/targhooks.h | 3 +- > 17 files changed, 768 insertions(+), 787 deletions(-) >
Ping. On 08/07/2026 15:46, Andrew Stubbs wrote: > Hi all, > > This patch series implements the "MEMs with address vectors" feature > that I want to use in AMD GCN, and have previously discussed on gcc@. > The motivation is to simplify a new back-end optimization pass I'm > working on and plan to post in the coming weeks. > > The first patch, in this series, is the middle-end enablement and > documentation changes. > > The second patch converts the amdgcn back-end to use the new scheme, > without adding any real new features. It depends on the > INSN_BASE_REG_CLASS patch I posted last week (still in review) to run > correctly. > > The third and final patch demonstrates how I can use the new MEM to > extend my machine description without writing whole new insns for the > vector modes, just for them to evaluate to the same assembler code in > the end. > > I have not yet finished testing the patches, so these might not be quite > the final form, but I'm not expecting big changes to the middle-end > portion. (I can self-approve the amdgcn parts, once the other is > committed, but comments are welcome.) > > OK for mainline? (Pending test results.) > > Thanks > > Andrew Stubbs (3): > rtl: Allow "(mem:<vecmode> (reg:<vecmode>))" > amdgcn: Implement "(mem (reg:<vecmode>))" > amdgcn: Add vector atomics > > gcc/config/gcn/constraints.md | 49 ++- > gcc/config/gcn/gcn-protos.h | 10 +- > gcc/config/gcn/gcn-valu.md | 745 ++++++++++++---------------------- > gcc/config/gcn/gcn.cc | 529 +++++++++++++----------- > gcc/config/gcn/gcn.h | 1 + > gcc/config/gcn/gcn.md | 123 +++--- > gcc/doc/rtl.texi | 8 + > gcc/doc/tm.texi | 13 +- > gcc/emit-rtl.cc | 30 +- > gcc/explow.cc | 12 +- > gcc/recog.cc | 4 +- > gcc/rtl.h | 2 +- > gcc/rtlanal.cc | 4 +- > gcc/simplify-rtx.cc | 5 +- > gcc/target.def | 13 +- > gcc/targhooks.cc | 4 +- > gcc/targhooks.h | 3 +- > 17 files changed, 768 insertions(+), 787 deletions(-) >
On Wed, Jul 8, 2026 at 4:48 PM Andrew Stubbs <ams@baylibre.com> wrote: > > Hi all, > > This patch series implements the "MEMs with address vectors" feature > that I want to use in AMD GCN, and have previously discussed on gcc@. > The motivation is to simplify a new back-end optimization pass I'm > working on and plan to post in the coming weeks. > > The first patch, in this series, is the middle-end enablement and > documentation changes. > > The second patch converts the amdgcn back-end to use the new scheme, > without adding any real new features. It depends on the > INSN_BASE_REG_CLASS patch I posted last week (still in review) to run > correctly. > > The third and final patch demonstrates how I can use the new MEM to > extend my machine description without writing whole new insns for the > vector modes, just for them to evaluate to the same assembler code in > the end. > > I have not yet finished testing the patches, so these might not be quite > the final form, but I'm not expecting big changes to the middle-end > portion. (I can self-approve the amdgcn parts, once the other is > committed, but comments are welcome.) > > OK for mainline? (Pending test results.) I think this exposes what GCN does in a natural way. I'm not sure the advantage (exposing former gather/scatter as move) is not also its disadvantage (moves are special!), and I somewhat question the benefit over using some UNSPEC for this. For example I would assume that you side-step RTL alias/dependence analysis, meaning these are barriers for optimization and scheduling? The proposed semantics (overlap has undefined behavior) does not match up with usual vector ISA scatter semantics (left-to-right), so the representation isn't universally useable (if we solve the masking issue). That said, my overall hunch is that we're extending general RTL semantics in a somewhat ad-hoc (and incomplete?) way. Not that I have a better idea here. Thanks, Richard. > > Thanks > > Andrew Stubbs (3): > rtl: Allow "(mem:<vecmode> (reg:<vecmode>))" > amdgcn: Implement "(mem (reg:<vecmode>))" > amdgcn: Add vector atomics > > gcc/config/gcn/constraints.md | 49 ++- > gcc/config/gcn/gcn-protos.h | 10 +- > gcc/config/gcn/gcn-valu.md | 745 ++++++++++++---------------------- > gcc/config/gcn/gcn.cc | 529 +++++++++++++----------- > gcc/config/gcn/gcn.h | 1 + > gcc/config/gcn/gcn.md | 123 +++--- > gcc/doc/rtl.texi | 8 + > gcc/doc/tm.texi | 13 +- > gcc/emit-rtl.cc | 30 +- > gcc/explow.cc | 12 +- > gcc/recog.cc | 4 +- > gcc/rtl.h | 2 +- > gcc/rtlanal.cc | 4 +- > gcc/simplify-rtx.cc | 5 +- > gcc/target.def | 13 +- > gcc/targhooks.cc | 4 +- > gcc/targhooks.h | 3 +- > 17 files changed, 768 insertions(+), 787 deletions(-) > > -- > 2.54.0 >
On 17/07/2026 09:13, Richard Biener wrote: > On Wed, Jul 8, 2026 at 4:48 PM Andrew Stubbs <ams@baylibre.com> wrote: >> >> Hi all, >> >> This patch series implements the "MEMs with address vectors" feature >> that I want to use in AMD GCN, and have previously discussed on gcc@. >> The motivation is to simplify a new back-end optimization pass I'm >> working on and plan to post in the coming weeks. >> >> The first patch, in this series, is the middle-end enablement and >> documentation changes. >> >> The second patch converts the amdgcn back-end to use the new scheme, >> without adding any real new features. It depends on the >> INSN_BASE_REG_CLASS patch I posted last week (still in review) to run >> correctly. >> >> The third and final patch demonstrates how I can use the new MEM to >> extend my machine description without writing whole new insns for the >> vector modes, just for them to evaluate to the same assembler code in >> the end. >> >> I have not yet finished testing the patches, so these might not be quite >> the final form, but I'm not expecting big changes to the middle-end >> portion. (I can self-approve the amdgcn parts, once the other is >> committed, but comments are welcome.) >> >> OK for mainline? (Pending test results.) > > I think this exposes what GCN does in a natural way. I'm not sure > the advantage (exposing former gather/scatter as move) is not > also its disadvantage (moves are special!), and I somewhat question > the benefit over using some UNSPEC for this. For example I would > assume that you side-step RTL alias/dependence analysis, meaning these > are barriers for optimization and scheduling? This is intended to be an enabling technology for my real project, in which I want to transform scalar operations into vector operations in the backend, and the special casing for memory accesses was getting out of hand. By expressing (unmasked) vector operations identically to the scalar equivalent I can simplify things greatly, and the other compiler passes can do (some of) their special MEM handling as they normally would. > The proposed semantics (overlap has undefined behavior) does not > match up with usual vector ISA scatter semantics (left-to-right), so > the representation isn't universally useable (if we solve the masking > issue). Unfortunately, this is the semantics of the hardware; specifying any other assumptions in the compiler might mean that it wouldn't be safe to use it for GCN. (It might be the case that the hardware is deterministic in practice, but the details are not documented in the ISA manuals; it just says that it will "write-combine data across the work-items".) We can say that "the compiler assumes the UB doesn't happen", and trust that the algorithm is constructed such that this is true. (It certainly should be the case for the code I'm generating.) I'm not familiar with the parts of the compiler where these assumptions are made. I don't believe I have specifically disabled any such analysis, but if something somewhere has a "return false" rather than a fatal assertion then I suppose I wouldn't have seen it. > That said, my overall hunch is that we're extending general RTL > semantics in a somewhat ad-hoc (and incomplete?) way. Not > that I have a better idea here. I prefer "incremental" to "incomplete", and as ad-hoc designs go it feels fairly natural, given what I want to represent. If time and money were no issue I could certainly spend a lot longer designing and implementing this feature, but it's a sub-project of a task order that comes with a budget and a deadline, so I've implemented as much of it as is necessary and I can test without constructing testcases for hypothetical use-cases. > Thanks, > Richard. > >> >> Thanks >> >> Andrew Stubbs (3): >> rtl: Allow "(mem:<vecmode> (reg:<vecmode>))" >> amdgcn: Implement "(mem (reg:<vecmode>))" >> amdgcn: Add vector atomics >> >> gcc/config/gcn/constraints.md | 49 ++- >> gcc/config/gcn/gcn-protos.h | 10 +- >> gcc/config/gcn/gcn-valu.md | 745 ++++++++++++---------------------- >> gcc/config/gcn/gcn.cc | 529 +++++++++++++----------- >> gcc/config/gcn/gcn.h | 1 + >> gcc/config/gcn/gcn.md | 123 +++--- >> gcc/doc/rtl.texi | 8 + >> gcc/doc/tm.texi | 13 +- >> gcc/emit-rtl.cc | 30 +- >> gcc/explow.cc | 12 +- >> gcc/recog.cc | 4 +- >> gcc/rtl.h | 2 +- >> gcc/rtlanal.cc | 4 +- >> gcc/simplify-rtx.cc | 5 +- >> gcc/target.def | 13 +- >> gcc/targhooks.cc | 4 +- >> gcc/targhooks.h | 3 +- >> 17 files changed, 768 insertions(+), 787 deletions(-) >> >> -- >> 2.54.0 >>
On Fri, Jul 17, 2026 at 12:13 PM Andrew Stubbs <ams@baylibre.com> wrote: > > On 17/07/2026 09:13, Richard Biener wrote: > > On Wed, Jul 8, 2026 at 4:48 PM Andrew Stubbs <ams@baylibre.com> wrote: > >> > >> Hi all, > >> > >> This patch series implements the "MEMs with address vectors" feature > >> that I want to use in AMD GCN, and have previously discussed on gcc@. > >> The motivation is to simplify a new back-end optimization pass I'm > >> working on and plan to post in the coming weeks. > >> > >> The first patch, in this series, is the middle-end enablement and > >> documentation changes. > >> > >> The second patch converts the amdgcn back-end to use the new scheme, > >> without adding any real new features. It depends on the > >> INSN_BASE_REG_CLASS patch I posted last week (still in review) to run > >> correctly. > >> > >> The third and final patch demonstrates how I can use the new MEM to > >> extend my machine description without writing whole new insns for the > >> vector modes, just for them to evaluate to the same assembler code in > >> the end. > >> > >> I have not yet finished testing the patches, so these might not be quite > >> the final form, but I'm not expecting big changes to the middle-end > >> portion. (I can self-approve the amdgcn parts, once the other is > >> committed, but comments are welcome.) > >> > >> OK for mainline? (Pending test results.) > > > > I think this exposes what GCN does in a natural way. I'm not sure > > the advantage (exposing former gather/scatter as move) is not > > also its disadvantage (moves are special!), and I somewhat question > > the benefit over using some UNSPEC for this. For example I would > > assume that you side-step RTL alias/dependence analysis, meaning these > > are barriers for optimization and scheduling? > > This is intended to be an enabling technology for my real project, in > which I want to transform scalar operations into vector operations in > the backend, and the special casing for memory accesses was getting out > of hand. By expressing (unmasked) vector operations identically to the > scalar equivalent I can simplify things greatly, and the other compiler > passes can do (some of) their special MEM handling as they normally would. I see. I guess you ruled out a ([parallel (set (mem:<scalar> ...) (...)) (set (mem:<scalar> ...) (...))]) etc. with vector extracts for the address. At least for "transform scalar ops to vectors" the actual representation of the MEM could be a black box as long as you have addresses in vectors (which is possible already). > > The proposed semantics (overlap has undefined behavior) does not > > match up with usual vector ISA scatter semantics (left-to-right), so > > the representation isn't universally useable (if we solve the masking > > issue). > > Unfortunately, this is the semantics of the hardware; specifying any > other assumptions in the compiler might mean that it wouldn't be safe to > use it for GCN. (It might be the case that the hardware is deterministic > in practice, but the details are not documented in the ISA manuals; it > just says that it will "write-combine data across the work-items".) Yeah, I think your proposed semantic is fine, it's just unfortunate we cannot make use of it elsewhere. > We can say that "the compiler assumes the UB doesn't happen", and trust > that the algorithm is constructed such that this is true. (It certainly > should be the case for the code I'm generating.) I'm not familiar with > the parts of the compiler where these assumptions are made. I don't > believe I have specifically disabled any such analysis, but if something > somewhere has a "return false" rather than a fatal assertion then I > suppose I wouldn't have seen it. > > > That said, my overall hunch is that we're extending general RTL > > semantics in a somewhat ad-hoc (and incomplete?) way. Not > > that I have a better idea here. > > I prefer "incremental" to "incomplete", and as ad-hoc designs go it > feels fairly natural, given what I want to represent. If time and money > were no issue I could certainly spend a lot longer designing and > implementing this feature, but it's a sub-project of a task order that > comes with a budget and a deadline, so I've implemented as much of it as > is necessary and I can test without constructing testcases for > hypothetical use-cases. Sure. Richard. > > > > Thanks, > > Richard. > > > >> > >> Thanks > >> > >> Andrew Stubbs (3): > >> rtl: Allow "(mem:<vecmode> (reg:<vecmode>))" > >> amdgcn: Implement "(mem (reg:<vecmode>))" > >> amdgcn: Add vector atomics > >> > >> gcc/config/gcn/constraints.md | 49 ++- > >> gcc/config/gcn/gcn-protos.h | 10 +- > >> gcc/config/gcn/gcn-valu.md | 745 ++++++++++++---------------------- > >> gcc/config/gcn/gcn.cc | 529 +++++++++++++----------- > >> gcc/config/gcn/gcn.h | 1 + > >> gcc/config/gcn/gcn.md | 123 +++--- > >> gcc/doc/rtl.texi | 8 + > >> gcc/doc/tm.texi | 13 +- > >> gcc/emit-rtl.cc | 30 +- > >> gcc/explow.cc | 12 +- > >> gcc/recog.cc | 4 +- > >> gcc/rtl.h | 2 +- > >> gcc/rtlanal.cc | 4 +- > >> gcc/simplify-rtx.cc | 5 +- > >> gcc/target.def | 13 +- > >> gcc/targhooks.cc | 4 +- > >> gcc/targhooks.h | 3 +- > >> 17 files changed, 768 insertions(+), 787 deletions(-) > >> > >> -- > >> 2.54.0 > >> >
On 17/07/2026 11:48, Richard Biener wrote: > On Fri, Jul 17, 2026 at 12:13 PM Andrew Stubbs <ams@baylibre.com> wrote: >> >> On 17/07/2026 09:13, Richard Biener wrote: >>> On Wed, Jul 8, 2026 at 4:48 PM Andrew Stubbs <ams@baylibre.com> wrote: >>>> >>>> Hi all, >>>> >>>> This patch series implements the "MEMs with address vectors" feature >>>> that I want to use in AMD GCN, and have previously discussed on gcc@. >>>> The motivation is to simplify a new back-end optimization pass I'm >>>> working on and plan to post in the coming weeks. >>>> >>>> The first patch, in this series, is the middle-end enablement and >>>> documentation changes. >>>> >>>> The second patch converts the amdgcn back-end to use the new scheme, >>>> without adding any real new features. It depends on the >>>> INSN_BASE_REG_CLASS patch I posted last week (still in review) to run >>>> correctly. >>>> >>>> The third and final patch demonstrates how I can use the new MEM to >>>> extend my machine description without writing whole new insns for the >>>> vector modes, just for them to evaluate to the same assembler code in >>>> the end. >>>> >>>> I have not yet finished testing the patches, so these might not be quite >>>> the final form, but I'm not expecting big changes to the middle-end >>>> portion. (I can self-approve the amdgcn parts, once the other is >>>> committed, but comments are welcome.) >>>> >>>> OK for mainline? (Pending test results.) >>> >>> I think this exposes what GCN does in a natural way. I'm not sure >>> the advantage (exposing former gather/scatter as move) is not >>> also its disadvantage (moves are special!), and I somewhat question >>> the benefit over using some UNSPEC for this. For example I would >>> assume that you side-step RTL alias/dependence analysis, meaning these >>> are barriers for optimization and scheduling? >> >> This is intended to be an enabling technology for my real project, in >> which I want to transform scalar operations into vector operations in >> the backend, and the special casing for memory accesses was getting out >> of hand. By expressing (unmasked) vector operations identically to the >> scalar equivalent I can simplify things greatly, and the other compiler >> passes can do (some of) their special MEM handling as they normally would. > > I see. I guess you ruled out a > > ([parallel > (set (mem:<scalar> ...) (...)) > (set (mem:<scalar> ...) (...))]) I would need this insn for V2, V4, V8, V16, V32, and V64. And probably SI/SF, DI/DF, and TI variants of each of those too (maybe QI and HI also). It would be very verbose, and what would the constraints even look like? Not to mention it's right back to the special-case conversions I was trying to avoid in the first place. > etc. with vector extracts for the address. At least for "transform scalar ops > to vectors" the actual representation of the MEM could be a black box > as long as you > have addresses in vectors (which is possible already). I'm not really sure what this means. Can you give an example, please? Andrew
> This is intended to be an enabling technology for my real project, in which I > want to transform scalar operations into vector operations in the backend, > and the special casing for memory accesses was getting out of hand. By > expressing (unmasked) vector operations identically to the scalar equivalent > I can simplify things greatly, and the other compiler passes can do (some of) > their special MEM handling as they normally would. Could you sketch what you want to achieve? I'm just trying to get an idea of what the "option space" is. Like, could you do your transform at gimple level? If that were possible, things could maybe just stay opaque at RTL level? Maybe related: I have been starting with "native" vector masking for RTL via a "vec_predicate" and I wonder if your requirements could influence the design of predicated movs, loads, and stores. But that's a separate topic.
On 17/07/2026 17:07, Robin Dapp wrote: >> This is intended to be an enabling technology for my real project, in which I >> want to transform scalar operations into vector operations in the backend, >> and the special casing for memory accesses was getting out of hand. By >> expressing (unmasked) vector operations identically to the scalar equivalent >> I can simplify things greatly, and the other compiler passes can do (some of) >> their special MEM handling as they normally would. > > Could you sketch what you want to achieve? I'm just trying to get an idea of > what the "option space" is. Like, could you do your transform at gimple level? > If that were possible, things could maybe just stay opaque at RTL level? It's essentially vectorization in the backend, for code with specific attributes. I definitely do not want to do it at gimple level because that would have the exact same problems that the existing vectorizer has. For example, in most cases I can simply transform (set (reg:SI) (plus:SI (reg:SI) (const_int))) into (set (reg:V64SI) (plus:V64SI (reg:V64SI) (const_vector:V64SI))) which makes total sense and Just Works on AMD GCN for almost all instructions. So, I want to do the same thing for a MEM: (set (reg:SI) (mem:SI (reg:DI))) becomes (set (reg:V64SI) (mem:V64SI (reg:V64DI))) except that the MEM is not valid because the address "isn't valid". There's no reason it shouldn't work on the architecture -- the two RTL patterns here will emit the *exact same* assembler code (obviously I set the execution mask differently) -- it's just an old assumption built into the compiler. I considered just leaving the scalar representation for everything, but the register allocator needs to know when to allocate vector registers, and when not (for example, a vec_duplicate looks like a move, except that the source and destination registers are different classes), and stack spills still need the extra space, so that would have required a lot of different cludges. > Maybe related: I have been starting with "native" vector masking for RTL via a > "vec_predicate" and I wonder if your requirements could influence the design of > predicated movs, loads, and stores. But that's a separate topic. > It might be that a "vec_predicate" would be better than "vec_merge"? But if the register allocator can pull the MEM out of context then we didn't gain anything for the specific issues I discussed in the gcc@ thread. Andrew
> Am 17.07.2026 um 13:38 schrieb Andrew Stubbs <ams@baylibre.com>: > > On 17/07/2026 11:48, Richard Biener wrote: >>> On Fri, Jul 17, 2026 at 12:13 PM Andrew Stubbs <ams@baylibre.com> wrote: >>> >>> On 17/07/2026 09:13, Richard Biener wrote: >>>> On Wed, Jul 8, 2026 at 4:48 PM Andrew Stubbs <ams@baylibre.com> wrote: >>>>> >>>>> Hi all, >>>>> >>>>> This patch series implements the "MEMs with address vectors" feature >>>>> that I want to use in AMD GCN, and have previously discussed on gcc@. >>>>> The motivation is to simplify a new back-end optimization pass I'm >>>>> working on and plan to post in the coming weeks. >>>>> >>>>> The first patch, in this series, is the middle-end enablement and >>>>> documentation changes. >>>>> >>>>> The second patch converts the amdgcn back-end to use the new scheme, >>>>> without adding any real new features. It depends on the >>>>> INSN_BASE_REG_CLASS patch I posted last week (still in review) to run >>>>> correctly. >>>>> >>>>> The third and final patch demonstrates how I can use the new MEM to >>>>> extend my machine description without writing whole new insns for the >>>>> vector modes, just for them to evaluate to the same assembler code in >>>>> the end. >>>>> >>>>> I have not yet finished testing the patches, so these might not be quite >>>>> the final form, but I'm not expecting big changes to the middle-end >>>>> portion. (I can self-approve the amdgcn parts, once the other is >>>>> committed, but comments are welcome.) >>>>> >>>>> OK for mainline? (Pending test results.) >>>> >>>> I think this exposes what GCN does in a natural way. I'm not sure >>>> the advantage (exposing former gather/scatter as move) is not >>>> also its disadvantage (moves are special!), and I somewhat question >>>> the benefit over using some UNSPEC for this. For example I would >>>> assume that you side-step RTL alias/dependence analysis, meaning these >>>> are barriers for optimization and scheduling? >>> >>> This is intended to be an enabling technology for my real project, in >>> which I want to transform scalar operations into vector operations in >>> the backend, and the special casing for memory accesses was getting out >>> of hand. By expressing (unmasked) vector operations identically to the >>> scalar equivalent I can simplify things greatly, and the other compiler >>> passes can do (some of) their special MEM handling as they normally would. >> I see. I guess you ruled out a >> ([parallel >> (set (mem:<scalar> ...) (...)) >> (set (mem:<scalar> ...) (...))]) > > I would need this insn for V2, V4, V8, V16, V32, and V64. And probably SI/SF, DI/DF, and TI variants of each of those too (maybe QI and HI also). > > It would be very verbose, and what would the constraints even look like? > > Not to mention it's right back to the special-case conversions I was trying to avoid in the first place. > >> etc. with vector extracts for the address. At least for "transform scalar ops >> to vectors" the actual representation of the MEM could be a black box >> as long as you >> have addresses in vectors (which is possible already). > > I'm not really sure what this means. Can you give an example, please? I mean you can write in your pass ‚turn MEM into a vec op‘ but how this is reflected into RTL is a detail that shouldn’t concern the pass itself (aka it might be an arbitrary complex but recognizable construct) Richard > > Andrew
> It's essentially vectorization in the backend, for code with specific > attributes. I definitely do not want to do it at gimple level because that > would have the exact same problems that the existing vectorizer has. > For example, in most cases I can simply transform > > (set (reg:SI) (plus:SI (reg:SI) (const_int))) > > into > > (set (reg:V64SI) (plus:V64SI (reg:V64SI) (const_vector:V64SI))) > > which makes total sense and Just Works on AMD GCN for almost all > instructions. > > So, I want to do the same thing for a MEM: > > (set (reg:SI) (mem:SI (reg:DI))) > > becomes > > (set (reg:V64SI) (mem:V64SI (reg:V64DI))) > > except that the MEM is not valid because the address "isn't valid". > There's no reason it shouldn't work on the architecture -- the two RTL > patterns here will emit the *exact same* assembler code (obviously I set > the execution mask differently) -- it's just an old assumption built > into the compiler. I'm not sure I follow 100% so let me just spell it out for myself. You're probably trying to "just vectorize everything", like in a GPU/SIMT programming model? And obviously this clashes with the vectorizer which doesn't if-convert everything, bails, costs etc.? But I don't see how vectorization, even simple one, is easier at RTL level. What about divergence, calls, aliasing, loops? Or is your target much narrower? Even if narrow, for a proper gimple solution you'd need a "second vectorizer" with limited scope and predicated gimple (because our usual IFNs aren't comprehensive enough)? It would "just" eat all conditions turning them into masks. That's a long-term goal for the vectorizer as well BTW :) Then, however, you'd still have the representational problem post expand :/ A vec_predicate would be helpful there, but only if it supported moves, loads and stores, which my initial RFC skipped for the known reasons ("they are special"). I guess it's time to start thinking more about them but that's obviously the opposite of a quick solution... so nothing here will actually help you right away :/ > It might be that a "vec_predicate" would be better than "vec_merge"? But if > the register allocator can pull the MEM out of context then we didn't gain > anything for the specific issues I discussed in the gcc@ thread. Yeah, one of the main reasons for vec_predicate as a "first-class" citizen is that we should not be able use its constituents context free. Under that model a vec_merge is already an atomic operation, a predicated reg-move. I wouldn't re-use vec_merge of course but we'd have something like (set (reg...) (vec_predicate [(reg ...)] vmask velse ...))
On Fri, Jul 17, 2026 at 10:40 PM Robin Dapp <rdapp.gcc@gmail.com> wrote: > > > It's essentially vectorization in the backend, for code with specific > > attributes. I definitely do not want to do it at gimple level because that > > would have the exact same problems that the existing vectorizer has. > > > For example, in most cases I can simply transform > > > > (set (reg:SI) (plus:SI (reg:SI) (const_int))) > > > > into > > > > (set (reg:V64SI) (plus:V64SI (reg:V64SI) (const_vector:V64SI))) > > > > which makes total sense and Just Works on AMD GCN for almost all > > instructions. > > > > So, I want to do the same thing for a MEM: > > > > (set (reg:SI) (mem:SI (reg:DI))) > > > > becomes > > > > (set (reg:V64SI) (mem:V64SI (reg:V64DI))) > > > > except that the MEM is not valid because the address "isn't valid". > > There's no reason it shouldn't work on the architecture -- the two RTL > > patterns here will emit the *exact same* assembler code (obviously I set > > the execution mask differently) -- it's just an old assumption built > > into the compiler. > > I'm not sure I follow 100% so let me just spell it out for myself. You're > probably trying to "just vectorize everything", like in a GPU/SIMT programming > model? And obviously this clashes with the vectorizer which doesn't if-convert > everything, bails, costs etc.? > > But I don't see how vectorization, even simple one, is easier at RTL level. > What about divergence, calls, aliasing, loops? Or is your target much > narrower? > > Even if narrow, for a proper gimple solution you'd need a "second vectorizer" > with limited scope and predicated gimple (because our usual IFNs aren't > comprehensive enough)? It would "just" eat all conditions turning them into > masks. That's a long-term goal for the vectorizer as well BTW :) > > Then, however, you'd still have the representational problem post expand :/ > A vec_predicate would be helpful there, but only if it supported moves, loads > and stores, which my initial RFC skipped for the known reasons ("they are > special"). > > I guess it's time to start thinking more about them but that's obviously the > opposite of a quick solution... so nothing here will actually help you right > away :/ > > > It might be that a "vec_predicate" would be better than "vec_merge"? But if > > the register allocator can pull the MEM out of context then we didn't gain > > anything for the specific issues I discussed in the gcc@ thread. > > Yeah, one of the main reasons for vec_predicate as a "first-class" citizen is > that we should not be able use its constituents context free. Under that model > a vec_merge is already an atomic operation, a predicated reg-move. I wouldn't > re-use vec_merge of course but we'd have something like > (set (reg...) (vec_predicate [(reg ...)] vmask velse ...)) I'll note that (cond_exec ...) also needs to behave that way, so we have precedent. (vec_pred_set ...) maybe. > > -- > Regards > Robin >
On 17/07/2026 21:40, Robin Dapp wrote: >> It's essentially vectorization in the backend, for code with specific >> attributes. I definitely do not want to do it at gimple level because that >> would have the exact same problems that the existing vectorizer has. > >> For example, in most cases I can simply transform >> >> (set (reg:SI) (plus:SI (reg:SI) (const_int))) >> >> into >> >> (set (reg:V64SI) (plus:V64SI (reg:V64SI) (const_vector:V64SI))) >> >> which makes total sense and Just Works on AMD GCN for almost all >> instructions. >> >> So, I want to do the same thing for a MEM: >> >> (set (reg:SI) (mem:SI (reg:DI))) >> >> becomes >> >> (set (reg:V64SI) (mem:V64SI (reg:V64DI))) >> >> except that the MEM is not valid because the address "isn't valid". >> There's no reason it shouldn't work on the architecture -- the two RTL >> patterns here will emit the *exact same* assembler code (obviously I set >> the execution mask differently) -- it's just an old assumption built >> into the compiler. > > I'm not sure I follow 100% so let me just spell it out for myself. You're > probably trying to "just vectorize everything", like in a GPU/SIMT programming > model? And obviously this clashes with the vectorizer which doesn't if-convert > everything, bails, costs etc.? Yes, this is for the GPU, and yes, SIMT is the way to think of it. The vectorizer would not be enabled for this code. That would not go well! > But I don't see how vectorization, even simple one, is easier at RTL level. > What about divergence, calls, aliasing, loops? Or is your target much > narrower? Divergence is a high-level concept that does not really exist at the assembler level (GCN has fork/join instructions, but then says not to use them in all but "irreducible cases" -- they simply loop until all the mask variations are exhausted). Calls are not an issue in themselves (provided all parameters fit in registers). Aliasing is no more of an issue than it would be in the original scalar code because the threads are required to be "independent". Loops work just fine, as long as the masks are managed correctly. > Even if narrow, for a proper gimple solution you'd need a "second vectorizer" > with limited scope and predicated gimple (because our usual IFNs aren't > comprehensive enough)? It would "just" eat all conditions turning them into > masks. That's a long-term goal for the vectorizer as well BTW :) Some things are easier at gimple level, and some are easier at RTL. The RTL level requires fewer changes that end up in discussions like this one. ;-) > Then, however, you'd still have the representational problem post expand :/ > A vec_predicate would be helpful there, but only if it supported moves, loads > and stores, which my initial RFC skipped for the known reasons ("they are > special"). > > I guess it's time to start thinking more about them but that's obviously the > opposite of a quick solution... so nothing here will actually help you right > away :/ > >> It might be that a "vec_predicate" would be better than "vec_merge"? But if >> the register allocator can pull the MEM out of context then we didn't gain >> anything for the specific issues I discussed in the gcc@ thread. > > Yeah, one of the main reasons for vec_predicate as a "first-class" citizen is > that we should not be able use its constituents context free. Under that model > a vec_merge is already an atomic operation, a predicated reg-move. I wouldn't > re-use vec_merge of course but we'd have something like > (set (reg...) (vec_predicate [(reg ...)] vmask velse ...)) So, it would be another way to write vec_merge, but with different behaviours/restrictions in certain passes?
> Yes, this is for the GPU, and yes, SIMT is the way to think of it. The > vectorizer would not be enabled for this code. That would not go well! > >> But I don't see how vectorization, even simple one, is easier at RTL level. >> What about divergence, calls, aliasing, loops? Or is your target much >> narrower? > > Divergence is a high-level concept that does not really exist at the > assembler level (GCN has fork/join instructions, but then says not to > use them in all but "irreducible cases" -- they simply loop until all > the mask variations are exhausted). > > Calls are not an issue in themselves (provided all parameters fit in > registers). > > Aliasing is no more of an issue than it would be in the original scalar > code because the threads are required to be "independent". > > Loops work just fine, as long as the masks are managed correctly. > Some things are easier at gimple level, and some are easier at RTL. > The RTL level requires fewer changes that end up in discussions like > this one. ;-) So you're transforming scalar "kernels" to SIMT and all prerequisites are already checked? I don't think I'll be able to get a full picture of your use case but to me it still sounds like a gimple-level problem, conceptually (when ignoring the fact that, currently, we cannot express it in gimple). >> Yeah, one of the main reasons for vec_predicate as a "first-class" citizen is >> that we should not be able use its constituents context free. Under that model >> a vec_merge is already an atomic operation, a predicated reg-move. I wouldn't >> re-use vec_merge of course but we'd have something like >> (set (reg...) (vec_predicate [(reg ...)] vmask velse ...)) > > So, it would be another way to write vec_merge, but with different > behaviours/restrictions in certain passes? A vec_merge is just a merge of two unpredicated inputs, vec_predicate is supposed to directly represent predication with mask, length etc. so a bit more comprehensive than vec_merge. Also, the intention is to make predication/masking more regular in the RTL passes. Once it gets interesting, i.e. stores, moves, vec_predicate alone also isn't enough. But as indicated, separate topic and doesn't help you directly here, apologies for derailing.
> On Wed, Jul 8, 2026 at 4:48 PM Andrew Stubbs <ams@baylibre.com> wrote: >> >> Hi all, >> >> This patch series implements the "MEMs with address vectors" feature >> that I want to use in AMD GCN, and have previously discussed on gcc@. >> The motivation is to simplify a new back-end optimization pass I'm >> working on and plan to post in the coming weeks. >> >> The first patch, in this series, is the middle-end enablement and >> documentation changes. >> >> The second patch converts the amdgcn back-end to use the new scheme, >> without adding any real new features. It depends on the >> INSN_BASE_REG_CLASS patch I posted last week (still in review) to run >> correctly. >> >> The third and final patch demonstrates how I can use the new MEM to >> extend my machine description without writing whole new insns for the >> vector modes, just for them to evaluate to the same assembler code in >> the end. >> >> I have not yet finished testing the patches, so these might not be quite >> the final form, but I'm not expecting big changes to the middle-end >> portion. (I can self-approve the amdgcn parts, once the other is >> committed, but comments are welcome.) >> >> OK for mainline? (Pending test results.) > > I think this exposes what GCN does in a natural way. I'm not sure > the advantage (exposing former gather/scatter as move) is not > also its disadvantage (moves are special!), and I somewhat question > the benefit over using some UNSPEC for this. For example I would > assume that you side-step RTL alias/dependence analysis, meaning these > are barriers for optimization and scheduling? > > The proposed semantics (overlap has undefined behavior) does not > match up with usual vector ISA scatter semantics (left-to-right), so > the representation isn't universally useable (if we solve the masking > issue). I just realized that we use the unordered flavor for scatters in RVV... Right now, the only reasonable thing a mem:<V> can represent is unordered accesses? And, as established in the RFC thread, we definitely need at least a non-overlap flag if it is supposed to be useful for scatter? And how would we even determine non-overlap? I don't see that we even can, apart from the stride-0 case. So we would still need the hardware to operate left-to-right and mem:<V> would effectively become an unspec again. On top, IIRC we assume somewhere that for mem:<mode> GET_MODE_SIZE (<mode>) is the size of the accessed memory. I guess (mem:BLK (reg:V16SI)) was already discussed and considered bad/unwanted/worst of both worlds?
On Mon, Jul 20, 2026 at 10:50 PM Robin Dapp <rdapp.gcc@gmail.com> wrote: > > > On Wed, Jul 8, 2026 at 4:48 PM Andrew Stubbs <ams@baylibre.com> wrote: > >> > >> Hi all, > >> > >> This patch series implements the "MEMs with address vectors" feature > >> that I want to use in AMD GCN, and have previously discussed on gcc@. > >> The motivation is to simplify a new back-end optimization pass I'm > >> working on and plan to post in the coming weeks. > >> > >> The first patch, in this series, is the middle-end enablement and > >> documentation changes. > >> > >> The second patch converts the amdgcn back-end to use the new scheme, > >> without adding any real new features. It depends on the > >> INSN_BASE_REG_CLASS patch I posted last week (still in review) to run > >> correctly. > >> > >> The third and final patch demonstrates how I can use the new MEM to > >> extend my machine description without writing whole new insns for the > >> vector modes, just for them to evaluate to the same assembler code in > >> the end. > >> > >> I have not yet finished testing the patches, so these might not be quite > >> the final form, but I'm not expecting big changes to the middle-end > >> portion. (I can self-approve the amdgcn parts, once the other is > >> committed, but comments are welcome.) > >> > >> OK for mainline? (Pending test results.) > > > > I think this exposes what GCN does in a natural way. I'm not sure > > the advantage (exposing former gather/scatter as move) is not > > also its disadvantage (moves are special!), and I somewhat question > > the benefit over using some UNSPEC for this. For example I would > > assume that you side-step RTL alias/dependence analysis, meaning these > > are barriers for optimization and scheduling? > > > > The proposed semantics (overlap has undefined behavior) does not > > match up with usual vector ISA scatter semantics (left-to-right), so > > the representation isn't universally useable (if we solve the masking > > issue). > > I just realized that we use the unordered flavor for scatters in RVV... > > Right now, the only reasonable thing a mem:<V> can represent is > unordered accesses? And, as established in the RFC thread, we > definitely need at least a non-overlap flag if it is supposed to be > useful for scatter? And how would we even determine non-overlap? I > don't see that we even can, apart from the stride-0 case. I'll note that for this very reason the autovectorizer assumes scatters are left-to-right. As you say we cannot reasonably do a runtime check (OK, there's separate ISA on x86 to detect conflicts, but we do not utilize that). The md.texi docs for scatter_store roughly document that (we should make the For each element index @var{i} more explicit I guess). > So we would still need the hardware to operate left-to-right and mem:<V> > would effectively become an unspec again. On top, IIRC we assume > somewhere that for mem:<mode> GET_MODE_SIZE (<mode>) is the size of the > accessed memory. I guess (mem:BLK (reg:V16SI)) was already discussed > and considered bad/unwanted/worst of both worlds? > > -- > Regards > Robin >
On 17/07/2026 18:19, Richard Biener wrote: > > >> Am 17.07.2026 um 13:38 schrieb Andrew Stubbs <ams@baylibre.com>: >> >> On 17/07/2026 11:48, Richard Biener wrote: >>>> On Fri, Jul 17, 2026 at 12:13 PM Andrew Stubbs <ams@baylibre.com> wrote: >>>> >>>> On 17/07/2026 09:13, Richard Biener wrote: >>>>> On Wed, Jul 8, 2026 at 4:48 PM Andrew Stubbs <ams@baylibre.com> wrote: >>>>>> >>>>>> Hi all, >>>>>> >>>>>> This patch series implements the "MEMs with address vectors" feature >>>>>> that I want to use in AMD GCN, and have previously discussed on gcc@. >>>>>> The motivation is to simplify a new back-end optimization pass I'm >>>>>> working on and plan to post in the coming weeks. >>>>>> >>>>>> The first patch, in this series, is the middle-end enablement and >>>>>> documentation changes. >>>>>> >>>>>> The second patch converts the amdgcn back-end to use the new scheme, >>>>>> without adding any real new features. It depends on the >>>>>> INSN_BASE_REG_CLASS patch I posted last week (still in review) to run >>>>>> correctly. >>>>>> >>>>>> The third and final patch demonstrates how I can use the new MEM to >>>>>> extend my machine description without writing whole new insns for the >>>>>> vector modes, just for them to evaluate to the same assembler code in >>>>>> the end. >>>>>> >>>>>> I have not yet finished testing the patches, so these might not be quite >>>>>> the final form, but I'm not expecting big changes to the middle-end >>>>>> portion. (I can self-approve the amdgcn parts, once the other is >>>>>> committed, but comments are welcome.) >>>>>> >>>>>> OK for mainline? (Pending test results.) >>>>> >>>>> I think this exposes what GCN does in a natural way. I'm not sure >>>>> the advantage (exposing former gather/scatter as move) is not >>>>> also its disadvantage (moves are special!), and I somewhat question >>>>> the benefit over using some UNSPEC for this. For example I would >>>>> assume that you side-step RTL alias/dependence analysis, meaning these >>>>> are barriers for optimization and scheduling? >>>> >>>> This is intended to be an enabling technology for my real project, in >>>> which I want to transform scalar operations into vector operations in >>>> the backend, and the special casing for memory accesses was getting out >>>> of hand. By expressing (unmasked) vector operations identically to the >>>> scalar equivalent I can simplify things greatly, and the other compiler >>>> passes can do (some of) their special MEM handling as they normally would. >>> I see. I guess you ruled out a >>> ([parallel >>> (set (mem:<scalar> ...) (...)) >>> (set (mem:<scalar> ...) (...))]) >> >> I would need this insn for V2, V4, V8, V16, V32, and V64. And probably SI/SF, DI/DF, and TI variants of each of those too (maybe QI and HI also). >> >> It would be very verbose, and what would the constraints even look like? >> >> Not to mention it's right back to the special-case conversions I was trying to avoid in the first place. >> >>> etc. with vector extracts for the address. At least for "transform scalar ops >>> to vectors" the actual representation of the MEM could be a black box >>> as long as you >>> have addresses in vectors (which is possible already). >> >> I'm not really sure what this means. Can you give an example, please? > > I mean you can write in your pass ‚turn MEM into a vec op‘ but how this is reflected into RTL is a detail that shouldn’t concern the pass itself (aka it might be an arbitrary complex but recognizable construct) > The discussion seems to have run out of steam without producing a conclusion. How can I proceed with this patch review? Thanks Andrew
On Tue, Jul 28, 2026 at 11:00 AM Andrew Stubbs <ams@baylibre.com> wrote: > > On 17/07/2026 18:19, Richard Biener wrote: > > > > > >> Am 17.07.2026 um 13:38 schrieb Andrew Stubbs <ams@baylibre.com>: > >> > >> On 17/07/2026 11:48, Richard Biener wrote: > >>>> On Fri, Jul 17, 2026 at 12:13 PM Andrew Stubbs <ams@baylibre.com> wrote: > >>>> > >>>> On 17/07/2026 09:13, Richard Biener wrote: > >>>>> On Wed, Jul 8, 2026 at 4:48 PM Andrew Stubbs <ams@baylibre.com> wrote: > >>>>>> > >>>>>> Hi all, > >>>>>> > >>>>>> This patch series implements the "MEMs with address vectors" feature > >>>>>> that I want to use in AMD GCN, and have previously discussed on gcc@. > >>>>>> The motivation is to simplify a new back-end optimization pass I'm > >>>>>> working on and plan to post in the coming weeks. > >>>>>> > >>>>>> The first patch, in this series, is the middle-end enablement and > >>>>>> documentation changes. > >>>>>> > >>>>>> The second patch converts the amdgcn back-end to use the new scheme, > >>>>>> without adding any real new features. It depends on the > >>>>>> INSN_BASE_REG_CLASS patch I posted last week (still in review) to run > >>>>>> correctly. > >>>>>> > >>>>>> The third and final patch demonstrates how I can use the new MEM to > >>>>>> extend my machine description without writing whole new insns for the > >>>>>> vector modes, just for them to evaluate to the same assembler code in > >>>>>> the end. > >>>>>> > >>>>>> I have not yet finished testing the patches, so these might not be quite > >>>>>> the final form, but I'm not expecting big changes to the middle-end > >>>>>> portion. (I can self-approve the amdgcn parts, once the other is > >>>>>> committed, but comments are welcome.) > >>>>>> > >>>>>> OK for mainline? (Pending test results.) > >>>>> > >>>>> I think this exposes what GCN does in a natural way. I'm not sure > >>>>> the advantage (exposing former gather/scatter as move) is not > >>>>> also its disadvantage (moves are special!), and I somewhat question > >>>>> the benefit over using some UNSPEC for this. For example I would > >>>>> assume that you side-step RTL alias/dependence analysis, meaning these > >>>>> are barriers for optimization and scheduling? > >>>> > >>>> This is intended to be an enabling technology for my real project, in > >>>> which I want to transform scalar operations into vector operations in > >>>> the backend, and the special casing for memory accesses was getting out > >>>> of hand. By expressing (unmasked) vector operations identically to the > >>>> scalar equivalent I can simplify things greatly, and the other compiler > >>>> passes can do (some of) their special MEM handling as they normally would. > >>> I see. I guess you ruled out a > >>> ([parallel > >>> (set (mem:<scalar> ...) (...)) > >>> (set (mem:<scalar> ...) (...))]) > >> > >> I would need this insn for V2, V4, V8, V16, V32, and V64. And probably SI/SF, DI/DF, and TI variants of each of those too (maybe QI and HI also). > >> > >> It would be very verbose, and what would the constraints even look like? > >> > >> Not to mention it's right back to the special-case conversions I was trying to avoid in the first place. > >> > >>> etc. with vector extracts for the address. At least for "transform scalar ops > >>> to vectors" the actual representation of the MEM could be a black box > >>> as long as you > >>> have addresses in vectors (which is possible already). > >> > >> I'm not really sure what this means. Can you give an example, please? > > > > I mean you can write in your pass ‚turn MEM into a vec op‘ but how this is reflected into RTL is a detail that shouldn’t concern the pass itself (aka it might be an arbitrary complex but recognizable construct) > > > > The discussion seems to have run out of steam without producing a > conclusion. Heh, sorry. It's still that I do not like (mem:<vector> ) much, I think it does not capture the GCN case well which the (parallel [(set (mem:<scalar> ...]) variant would. That doesn't solve your pattern explosion/typing problem, of course. Maybe that can be solved by parametrizing that (ick) (parallel_vec:<vector> [(set (mem:<scalar> (subreg:DI ...) ...)]) so basically have a parallel that implicitly enumerates operations on all vector lanes of a mode. The (parallel ..) bit implies it's unordered. I'm not exactly sure about the subreg part for the address - some magic needs to happen for the subreg offset of course. Would this be too restrictive? I think GCN can actually do few (two?) lanes as actual vector operation in an ALU, but I guess we're not modeling that. That said, I do not want to stand in the way of (mem:<vector> ..) when there's consensus this is the best general way to address this. > How can I proceed with this patch review? > > Thanks > > Andrew
On 28/07/2026 11:22, Richard Biener wrote: > On Tue, Jul 28, 2026 at 11:00 AM Andrew Stubbs <ams@baylibre.com> wrote: >> >> On 17/07/2026 18:19, Richard Biener wrote: >>> >>> >>>> Am 17.07.2026 um 13:38 schrieb Andrew Stubbs <ams@baylibre.com>: >>>> >>>> On 17/07/2026 11:48, Richard Biener wrote: >>>>>> On Fri, Jul 17, 2026 at 12:13 PM Andrew Stubbs <ams@baylibre.com> wrote: >>>>>> >>>>>> On 17/07/2026 09:13, Richard Biener wrote: >>>>>>> On Wed, Jul 8, 2026 at 4:48 PM Andrew Stubbs <ams@baylibre.com> wrote: >>>>>>>> >>>>>>>> Hi all, >>>>>>>> >>>>>>>> This patch series implements the "MEMs with address vectors" feature >>>>>>>> that I want to use in AMD GCN, and have previously discussed on gcc@. >>>>>>>> The motivation is to simplify a new back-end optimization pass I'm >>>>>>>> working on and plan to post in the coming weeks. >>>>>>>> >>>>>>>> The first patch, in this series, is the middle-end enablement and >>>>>>>> documentation changes. >>>>>>>> >>>>>>>> The second patch converts the amdgcn back-end to use the new scheme, >>>>>>>> without adding any real new features. It depends on the >>>>>>>> INSN_BASE_REG_CLASS patch I posted last week (still in review) to run >>>>>>>> correctly. >>>>>>>> >>>>>>>> The third and final patch demonstrates how I can use the new MEM to >>>>>>>> extend my machine description without writing whole new insns for the >>>>>>>> vector modes, just for them to evaluate to the same assembler code in >>>>>>>> the end. >>>>>>>> >>>>>>>> I have not yet finished testing the patches, so these might not be quite >>>>>>>> the final form, but I'm not expecting big changes to the middle-end >>>>>>>> portion. (I can self-approve the amdgcn parts, once the other is >>>>>>>> committed, but comments are welcome.) >>>>>>>> >>>>>>>> OK for mainline? (Pending test results.) >>>>>>> >>>>>>> I think this exposes what GCN does in a natural way. I'm not sure >>>>>>> the advantage (exposing former gather/scatter as move) is not >>>>>>> also its disadvantage (moves are special!), and I somewhat question >>>>>>> the benefit over using some UNSPEC for this. For example I would >>>>>>> assume that you side-step RTL alias/dependence analysis, meaning these >>>>>>> are barriers for optimization and scheduling? >>>>>> >>>>>> This is intended to be an enabling technology for my real project, in >>>>>> which I want to transform scalar operations into vector operations in >>>>>> the backend, and the special casing for memory accesses was getting out >>>>>> of hand. By expressing (unmasked) vector operations identically to the >>>>>> scalar equivalent I can simplify things greatly, and the other compiler >>>>>> passes can do (some of) their special MEM handling as they normally would. >>>>> I see. I guess you ruled out a >>>>> ([parallel >>>>> (set (mem:<scalar> ...) (...)) >>>>> (set (mem:<scalar> ...) (...))]) >>>> >>>> I would need this insn for V2, V4, V8, V16, V32, and V64. And probably SI/SF, DI/DF, and TI variants of each of those too (maybe QI and HI also). >>>> >>>> It would be very verbose, and what would the constraints even look like? >>>> >>>> Not to mention it's right back to the special-case conversions I was trying to avoid in the first place. >>>> >>>>> etc. with vector extracts for the address. At least for "transform scalar ops >>>>> to vectors" the actual representation of the MEM could be a black box >>>>> as long as you >>>>> have addresses in vectors (which is possible already). >>>> >>>> I'm not really sure what this means. Can you give an example, please? >>> >>> I mean you can write in your pass ‚turn MEM into a vec op‘ but how this is reflected into RTL is a detail that shouldn’t concern the pass itself (aka it might be an arbitrary complex but recognizable construct) >>> >> >> The discussion seems to have run out of steam without producing a >> conclusion. > > Heh, sorry. It's still that I do not like (mem:<vector> ) much, I > think it does not capture > the GCN case well which the (parallel [(set (mem:<scalar> ...]) > variant would. That > doesn't solve your pattern explosion/typing problem, of course. I don't know how the constraints would even work? (parallel [(set (match_operand:<scalar> 0 "memory_operand" "v") (...)) (set (match_operand:<scalar> 1 "memory_operand" "0") (...)) .... Or does it use (match_dup 0)? There are 64 notional scalar operands that are somehow all in the same register. I don't know how to express that. > Maybe that can be > solved by parametrizing that (ick) > > (parallel_vec:<vector> > [(set (mem:<scalar> (subreg:DI ...) ...)]) > > so basically have a parallel that implicitly enumerates operations on all vector > lanes of a mode. The (parallel ..) bit implies it's unordered. That could work, although that's a whole project in itself, and you'd probably want to express all vector operations that way or else you'll end up having to convert between them. And you'd have to stop the combine pass trying to insert actual scalars into parallel_vec patterns because they look like they'd fit. > I'm not exactly sure> about the subreg part for the address - some magic needs to happen for the > subreg offset of course. Subregs are already basically unusable for GCN because the implied operation just doesn't fit when you can't reinterpret the entire vector with a different number of lanes. I want a "vsubreg" which refers to a portion of each lane, but I also don't want to completely rewrite the compiler to handle that everywhere it would come up. > Would this be > too restrictive? I think GCN can actually do few (two?) lanes as actual vector > operation in an ALU, but I guess we're not modeling that. As far as I know, the GPU does everything x64 in parallel. I'm sure there's some hidden implementation details in there, but those are not in the ISA manual. > That said, I do not want to stand in the way of (mem:<vector> ..) when there's > consensus this is the best general way to address this. Thank you. >> How can I proceed with this patch review? >> >> Thanks >> >> Andrew
On Tue, Jul 28, 2026 at 12:40 PM Andrew Stubbs <ams@baylibre.com> wrote: > > On 28/07/2026 11:22, Richard Biener wrote: > > On Tue, Jul 28, 2026 at 11:00 AM Andrew Stubbs <ams@baylibre.com> wrote: > >> > >> On 17/07/2026 18:19, Richard Biener wrote: > >>> > >>> > >>>> Am 17.07.2026 um 13:38 schrieb Andrew Stubbs <ams@baylibre.com>: > >>>> > >>>> On 17/07/2026 11:48, Richard Biener wrote: > >>>>>> On Fri, Jul 17, 2026 at 12:13 PM Andrew Stubbs <ams@baylibre.com> wrote: > >>>>>> > >>>>>> On 17/07/2026 09:13, Richard Biener wrote: > >>>>>>> On Wed, Jul 8, 2026 at 4:48 PM Andrew Stubbs <ams@baylibre.com> wrote: > >>>>>>>> > >>>>>>>> Hi all, > >>>>>>>> > >>>>>>>> This patch series implements the "MEMs with address vectors" feature > >>>>>>>> that I want to use in AMD GCN, and have previously discussed on gcc@. > >>>>>>>> The motivation is to simplify a new back-end optimization pass I'm > >>>>>>>> working on and plan to post in the coming weeks. > >>>>>>>> > >>>>>>>> The first patch, in this series, is the middle-end enablement and > >>>>>>>> documentation changes. > >>>>>>>> > >>>>>>>> The second patch converts the amdgcn back-end to use the new scheme, > >>>>>>>> without adding any real new features. It depends on the > >>>>>>>> INSN_BASE_REG_CLASS patch I posted last week (still in review) to run > >>>>>>>> correctly. > >>>>>>>> > >>>>>>>> The third and final patch demonstrates how I can use the new MEM to > >>>>>>>> extend my machine description without writing whole new insns for the > >>>>>>>> vector modes, just for them to evaluate to the same assembler code in > >>>>>>>> the end. > >>>>>>>> > >>>>>>>> I have not yet finished testing the patches, so these might not be quite > >>>>>>>> the final form, but I'm not expecting big changes to the middle-end > >>>>>>>> portion. (I can self-approve the amdgcn parts, once the other is > >>>>>>>> committed, but comments are welcome.) > >>>>>>>> > >>>>>>>> OK for mainline? (Pending test results.) > >>>>>>> > >>>>>>> I think this exposes what GCN does in a natural way. I'm not sure > >>>>>>> the advantage (exposing former gather/scatter as move) is not > >>>>>>> also its disadvantage (moves are special!), and I somewhat question > >>>>>>> the benefit over using some UNSPEC for this. For example I would > >>>>>>> assume that you side-step RTL alias/dependence analysis, meaning these > >>>>>>> are barriers for optimization and scheduling? > >>>>>> > >>>>>> This is intended to be an enabling technology for my real project, in > >>>>>> which I want to transform scalar operations into vector operations in > >>>>>> the backend, and the special casing for memory accesses was getting out > >>>>>> of hand. By expressing (unmasked) vector operations identically to the > >>>>>> scalar equivalent I can simplify things greatly, and the other compiler > >>>>>> passes can do (some of) their special MEM handling as they normally would. > >>>>> I see. I guess you ruled out a > >>>>> ([parallel > >>>>> (set (mem:<scalar> ...) (...)) > >>>>> (set (mem:<scalar> ...) (...))]) > >>>> > >>>> I would need this insn for V2, V4, V8, V16, V32, and V64. And probably SI/SF, DI/DF, and TI variants of each of those too (maybe QI and HI also). > >>>> > >>>> It would be very verbose, and what would the constraints even look like? > >>>> > >>>> Not to mention it's right back to the special-case conversions I was trying to avoid in the first place. > >>>> > >>>>> etc. with vector extracts for the address. At least for "transform scalar ops > >>>>> to vectors" the actual representation of the MEM could be a black box > >>>>> as long as you > >>>>> have addresses in vectors (which is possible already). > >>>> > >>>> I'm not really sure what this means. Can you give an example, please? > >>> > >>> I mean you can write in your pass ‚turn MEM into a vec op‘ but how this is reflected into RTL is a detail that shouldn’t concern the pass itself (aka it might be an arbitrary complex but recognizable construct) > >>> > >> > >> The discussion seems to have run out of steam without producing a > >> conclusion. > > > > Heh, sorry. It's still that I do not like (mem:<vector> ) much, I > > think it does not capture > > the GCN case well which the (parallel [(set (mem:<scalar> ...]) > > variant would. That > > doesn't solve your pattern explosion/typing problem, of course. > > I don't know how the constraints would even work? > > (parallel [(set (match_operand:<scalar> 0 "memory_operand" "v") (...)) > (set (match_operand:<scalar> 1 "memory_operand" "0") (...)) > .... > > Or does it use (match_dup 0)? There are 64 notional scalar operands that > are somehow all in the same register. I don't know how to express that. > > > Maybe that can be > > solved by parametrizing that (ick) > > > > (parallel_vec:<vector> > > [(set (mem:<scalar> (subreg:DI ...) ...)]) > > > > so basically have a parallel that implicitly enumerates operations on all vector > > lanes of a mode. The (parallel ..) bit implies it's unordered. > > That could work, although that's a whole project in itself, and you'd > probably want to express all vector operations that way or else you'll > end up having to convert between them. And you'd have to stop the > combine pass trying to insert actual scalars into parallel_vec patterns > because they look like they'd fit. > > > I'm not exactly sure> about the subreg part for the address - some > magic needs to happen for the > > subreg offset of course. > > Subregs are already basically unusable for GCN because the implied > operation just doesn't fit when you can't reinterpret the entire vector > with a different number of lanes. > > I want a "vsubreg" which refers to a portion of each lane, but I also > don't want to completely rewrite the compiler to handle that everywhere > it would come up. > > > Would this be > > too restrictive? I think GCN can actually do few (two?) lanes as actual vector > > operation in an ALU, but I guess we're not modeling that. > > As far as I know, the GPU does everything x64 in parallel. I'm sure > there's some hidden implementation details in there, but those are not > in the ISA manual. > > > That said, I do not want to stand in the way of (mem:<vector> ..) when there's > > consensus this is the best general way to address this. Just to add that (mem:<vector> ..) with unordered semantics ties us to that unless we want to have a flag on the mem to have left-to-right semantics. Given it in theory should be made to fit gather/scatter modelling (ignoring the masking representational issue). So I'd like at least that thought out, if not documented and implemented (having the flag and printing it). Richard. > > Thank you. > > > >> How can I proceed with this patch review? > >> > >> Thanks > >> > >> Andrew >
On 28/07/2026 12:54, Richard Biener wrote: > On Tue, Jul 28, 2026 at 12:40 PM Andrew Stubbs <ams@baylibre.com> wrote: >> >> On 28/07/2026 11:22, Richard Biener wrote: >>> On Tue, Jul 28, 2026 at 11:00 AM Andrew Stubbs <ams@baylibre.com> wrote: >>>> >>>> On 17/07/2026 18:19, Richard Biener wrote: >>>>> >>>>> >>>>>> Am 17.07.2026 um 13:38 schrieb Andrew Stubbs <ams@baylibre.com>: >>>>>> >>>>>> On 17/07/2026 11:48, Richard Biener wrote: >>>>>>>> On Fri, Jul 17, 2026 at 12:13 PM Andrew Stubbs <ams@baylibre.com> wrote: >>>>>>>> >>>>>>>> On 17/07/2026 09:13, Richard Biener wrote: >>>>>>>>> On Wed, Jul 8, 2026 at 4:48 PM Andrew Stubbs <ams@baylibre.com> wrote: >>>>>>>>>> >>>>>>>>>> Hi all, >>>>>>>>>> >>>>>>>>>> This patch series implements the "MEMs with address vectors" feature >>>>>>>>>> that I want to use in AMD GCN, and have previously discussed on gcc@. >>>>>>>>>> The motivation is to simplify a new back-end optimization pass I'm >>>>>>>>>> working on and plan to post in the coming weeks. >>>>>>>>>> >>>>>>>>>> The first patch, in this series, is the middle-end enablement and >>>>>>>>>> documentation changes. >>>>>>>>>> >>>>>>>>>> The second patch converts the amdgcn back-end to use the new scheme, >>>>>>>>>> without adding any real new features. It depends on the >>>>>>>>>> INSN_BASE_REG_CLASS patch I posted last week (still in review) to run >>>>>>>>>> correctly. >>>>>>>>>> >>>>>>>>>> The third and final patch demonstrates how I can use the new MEM to >>>>>>>>>> extend my machine description without writing whole new insns for the >>>>>>>>>> vector modes, just for them to evaluate to the same assembler code in >>>>>>>>>> the end. >>>>>>>>>> >>>>>>>>>> I have not yet finished testing the patches, so these might not be quite >>>>>>>>>> the final form, but I'm not expecting big changes to the middle-end >>>>>>>>>> portion. (I can self-approve the amdgcn parts, once the other is >>>>>>>>>> committed, but comments are welcome.) >>>>>>>>>> >>>>>>>>>> OK for mainline? (Pending test results.) >>>>>>>>> >>>>>>>>> I think this exposes what GCN does in a natural way. I'm not sure >>>>>>>>> the advantage (exposing former gather/scatter as move) is not >>>>>>>>> also its disadvantage (moves are special!), and I somewhat question >>>>>>>>> the benefit over using some UNSPEC for this. For example I would >>>>>>>>> assume that you side-step RTL alias/dependence analysis, meaning these >>>>>>>>> are barriers for optimization and scheduling? >>>>>>>> >>>>>>>> This is intended to be an enabling technology for my real project, in >>>>>>>> which I want to transform scalar operations into vector operations in >>>>>>>> the backend, and the special casing for memory accesses was getting out >>>>>>>> of hand. By expressing (unmasked) vector operations identically to the >>>>>>>> scalar equivalent I can simplify things greatly, and the other compiler >>>>>>>> passes can do (some of) their special MEM handling as they normally would. >>>>>>> I see. I guess you ruled out a >>>>>>> ([parallel >>>>>>> (set (mem:<scalar> ...) (...)) >>>>>>> (set (mem:<scalar> ...) (...))]) >>>>>> >>>>>> I would need this insn for V2, V4, V8, V16, V32, and V64. And probably SI/SF, DI/DF, and TI variants of each of those too (maybe QI and HI also). >>>>>> >>>>>> It would be very verbose, and what would the constraints even look like? >>>>>> >>>>>> Not to mention it's right back to the special-case conversions I was trying to avoid in the first place. >>>>>> >>>>>>> etc. with vector extracts for the address. At least for "transform scalar ops >>>>>>> to vectors" the actual representation of the MEM could be a black box >>>>>>> as long as you >>>>>>> have addresses in vectors (which is possible already). >>>>>> >>>>>> I'm not really sure what this means. Can you give an example, please? >>>>> >>>>> I mean you can write in your pass ‚turn MEM into a vec op‘ but how this is reflected into RTL is a detail that shouldn’t concern the pass itself (aka it might be an arbitrary complex but recognizable construct) >>>>> >>>> >>>> The discussion seems to have run out of steam without producing a >>>> conclusion. >>> >>> Heh, sorry. It's still that I do not like (mem:<vector> ) much, I >>> think it does not capture >>> the GCN case well which the (parallel [(set (mem:<scalar> ...]) >>> variant would. That >>> doesn't solve your pattern explosion/typing problem, of course. >> >> I don't know how the constraints would even work? >> >> (parallel [(set (match_operand:<scalar> 0 "memory_operand" "v") (...)) >> (set (match_operand:<scalar> 1 "memory_operand" "0") (...)) >> .... >> >> Or does it use (match_dup 0)? There are 64 notional scalar operands that >> are somehow all in the same register. I don't know how to express that. >> >>> Maybe that can be >>> solved by parametrizing that (ick) >>> >>> (parallel_vec:<vector> >>> [(set (mem:<scalar> (subreg:DI ...) ...)]) >>> >>> so basically have a parallel that implicitly enumerates operations on all vector >>> lanes of a mode. The (parallel ..) bit implies it's unordered. >> >> That could work, although that's a whole project in itself, and you'd >> probably want to express all vector operations that way or else you'll >> end up having to convert between them. And you'd have to stop the >> combine pass trying to insert actual scalars into parallel_vec patterns >> because they look like they'd fit. >> >> > I'm not exactly sure> about the subreg part for the address - some >> magic needs to happen for the >>> subreg offset of course. >> >> Subregs are already basically unusable for GCN because the implied >> operation just doesn't fit when you can't reinterpret the entire vector >> with a different number of lanes. >> >> I want a "vsubreg" which refers to a portion of each lane, but I also >> don't want to completely rewrite the compiler to handle that everywhere >> it would come up. >> >>> Would this be >>> too restrictive? I think GCN can actually do few (two?) lanes as actual vector >>> operation in an ALU, but I guess we're not modeling that. >> >> As far as I know, the GPU does everything x64 in parallel. I'm sure >> there's some hidden implementation details in there, but those are not >> in the ISA manual. >> >>> That said, I do not want to stand in the way of (mem:<vector> ..) when there's >>> consensus this is the best general way to address this. > > Just to add that (mem:<vector> ..) with unordered semantics ties us to that > unless we want to have a flag on the mem to have left-to-right semantics. > Given it in theory should be made to fit gather/scatter modelling (ignoring > the masking representational issue). So I'd like at least that thought out, > if not documented and implemented (having the flag and printing it). I believe the /i and /s flags are available, if we should choose to use them. Would a target hook not be sufficient though? These things are likely to be true always or never, for any given mode, on most architectures. Better even, as such flags are somewhat likely to "get lost" in all the random places that manipulate MEM. Andrew
Andrew Stubbs <ams@baylibre.com> writes: > On 28/07/2026 12:54, Richard Biener wrote: >> [...] >> Just to add that (mem:<vector> ..) with unordered semantics ties us to that >> unless we want to have a flag on the mem to have left-to-right semantics. >> Given it in theory should be made to fit gather/scatter modelling (ignoring >> the masking representational issue). So I'd like at least that thought out, >> if not documented and implemented (having the flag and printing it). Agreed FWIW. I think it would be good to think about the masking issue too, given Robin's parallel discussion about having a better representation of predication. Again, just in terms of having a plausible approach thought out, rather than being implemented in the first version. > I believe the /i and /s flags are available, if we should choose to use > them. > > Would a target hook not be sufficient though? These things are likely to > be true always or never, for any given mode, on most architectures. > > Better even, as such flags are somewhat likely to "get lost" in all the > random places that manipulate MEM. Please don't use a hook! :) IMO RTL semantics should stand on their own as far as possible. I realise there are exceptions, like STORE_FLAG_VALUE and SHIFT_COUNT_TRUNCATED, but even there, I think it would have been better to make the RTL operators self-descriptive and use the macros to control which operator is generated. Making SHIFT_COUNT_TRUNCATED apply to all shift rtxes has been a problem in the past and using a hook here might end up the same way. Thanks, Richard
On 28/07/2026 17:21, Richard Sandiford wrote: > Andrew Stubbs <ams@baylibre.com> writes: >> On 28/07/2026 12:54, Richard Biener wrote: >>> [...] >>> Just to add that (mem:<vector> ..) with unordered semantics ties us to that >>> unless we want to have a flag on the mem to have left-to-right semantics. >>> Given it in theory should be made to fit gather/scatter modelling (ignoring >>> the masking representational issue). So I'd like at least that thought out, >>> if not documented and implemented (having the flag and printing it). > > Agreed FWIW. > > I think it would be good to think about the masking issue too, given > Robin's parallel discussion about having a better representation of > predication. Again, just in terms of having a plausible approach > thought out, rather than being implemented in the first version. > >> I believe the /i and /s flags are available, if we should choose to use >> them. >> >> Would a target hook not be sufficient though? These things are likely to >> be true always or never, for any given mode, on most architectures. >> >> Better even, as such flags are somewhat likely to "get lost" in all the >> random places that manipulate MEM. > > Please don't use a hook! :) IMO RTL semantics should stand on their own > as far as possible. I realise there are exceptions, like STORE_FLAG_VALUE > and SHIFT_COUNT_TRUNCATED, but even there, I think it would have been > better to make the RTL operators self-descriptive and use the macros > to control which operator is generated. > > Making SHIFT_COUNT_TRUNCATED apply to all shift rtxes has been a problem > in the past and using a hook here might end up the same way. OK, let's say MEM_IN_ORDER_WRITE with /i then? If the flag is not present then the order is undefined. It could work the other way around, but this seemed to fit nicer with "i". How does it get written at expand time? Does the expand pass just assume that all gimple vector operators are "in-order"? Is there a hook for *that*? Ordered/unordered optabs? The legitimate/legitimize hooks can't do anything with flags because they only see the address expression. If we're just assuming in-order by default, the code produced would actually be unsuitable for GCN. Except it isn't, of course, because autovectorization (and OpenMP parallel, etc) require that the loop iterations are independent, and therefore we choose to assume (rightly or wrongly) that using the writes that we have are safe. But GCN would have to somehow go though and remove all those flags, or else whatever RTL optimizer it is that cares about such things would be getting misinformed. Andrew
> Am 28.07.2026 um 18:59 schrieb Andrew Stubbs <ams@baylibre.com>: > > On 28/07/2026 17:21, Richard Sandiford wrote: >> Andrew Stubbs <ams@baylibre.com> writes: >>>> On 28/07/2026 12:54, Richard Biener wrote: >>>>> [...] >>>>> Just to add that (mem:<vector> ..) with unordered semantics ties us to that >>>>> unless we want to have a flag on the mem to have left-to-right semantics. >>>>> Given it in theory should be made to fit gather/scatter modelling (ignoring >>>>> the masking representational issue). So I'd like at least that thought out, >>>>> if not documented and implemented (having the flag and printing it). >>> Agreed FWIW. >>> I think it would be good to think about the masking issue too, given >>> Robin's parallel discussion about having a better representation of >>> predication. Again, just in terms of having a plausible approach >>> thought out, rather than being implemented in the first version. >>> I believe the /i and /s flags are available, if we should choose to use >>> them. >>> >>> Would a target hook not be sufficient though? These things are likely to >>> be true always or never, for any given mode, on most architectures. >>> >>> Better even, as such flags are somewhat likely to "get lost" in all the >>> random places that manipulate MEM. >> Please don't use a hook! :) IMO RTL semantics should stand on their own >> as far as possible. I realise there are exceptions, like STORE_FLAG_VALUE >> and SHIFT_COUNT_TRUNCATED, but even there, I think it would have been >> better to make the RTL operators self-descriptive and use the macros >> to control which operator is generated. >> Making SHIFT_COUNT_TRUNCATED apply to all shift rtxes has been a problem >> in the past and using a hook here might end up the same way. > > OK, let's say MEM_IN_ORDER_WRITE with /i then? If the flag is not present then the order is undefined. It could work the other way around, but this seemed to fit nicer with "i". > > How does it get written at expand time? Does the expand pass just assume that all gimple vector operators are "in-order"? Is there a hook for *that*? Ordered/unordered optabs? The legitimate/legitimize hooks can't do anything with flags because they only see the address expression. The only way to get this from RTL expansion is through gather (order does not matter) and scatter (in-order required) both generated via optabs thus the flag is set from targets. And recog would somehow need to match on it as riscv can do both in-order and unspecified order. Richard > > If we're just assuming in-order by default, the code produced would actually be unsuitable for GCN. Except it isn't, of course, because autovectorization (and OpenMP parallel, etc) require that the loop iterations are independent, and therefore we choose to assume (rightly or wrongly) that using the writes that we have are safe. > > But GCN would have to somehow go though and remove all those flags, or else whatever RTL optimizer it is that cares about such things would be getting misinformed. > > Andrew
On 28/07/2026 18:17, Richard Biener wrote: > > >> Am 28.07.2026 um 18:59 schrieb Andrew Stubbs <ams@baylibre.com>: >> >> On 28/07/2026 17:21, Richard Sandiford wrote: >>> Andrew Stubbs <ams@baylibre.com> writes: >>>>> On 28/07/2026 12:54, Richard Biener wrote: >>>>>> [...] >>>>>> Just to add that (mem:<vector> ..) with unordered semantics ties us to that >>>>>> unless we want to have a flag on the mem to have left-to-right semantics. >>>>>> Given it in theory should be made to fit gather/scatter modelling (ignoring >>>>>> the masking representational issue). So I'd like at least that thought out, >>>>>> if not documented and implemented (having the flag and printing it). >>>> Agreed FWIW. >>>> I think it would be good to think about the masking issue too, given >>>> Robin's parallel discussion about having a better representation of >>>> predication. Again, just in terms of having a plausible approach >>>> thought out, rather than being implemented in the first version. >>>> I believe the /i and /s flags are available, if we should choose to use >>>> them. >>>> >>>> Would a target hook not be sufficient though? These things are likely to >>>> be true always or never, for any given mode, on most architectures. >>>> >>>> Better even, as such flags are somewhat likely to "get lost" in all the >>>> random places that manipulate MEM. >>> Please don't use a hook! :) IMO RTL semantics should stand on their own >>> as far as possible. I realise there are exceptions, like STORE_FLAG_VALUE >>> and SHIFT_COUNT_TRUNCATED, but even there, I think it would have been >>> better to make the RTL operators self-descriptive and use the macros >>> to control which operator is generated. >>> Making SHIFT_COUNT_TRUNCATED apply to all shift rtxes has been a problem >>> in the past and using a hook here might end up the same way. >> >> OK, let's say MEM_IN_ORDER_WRITE with /i then? If the flag is not present then the order is undefined. It could work the other way around, but this seemed to fit nicer with "i". >> >> How does it get written at expand time? Does the expand pass just assume that all gimple vector operators are "in-order"? Is there a hook for *that*? Ordered/unordered optabs? The legitimate/legitimize hooks can't do anything with flags because they only see the address expression. > > The only way to get this from RTL expansion is through gather (order does not matter) and scatter (in-order required) both generated via optabs thus the flag is set from targets. And recog would somehow need to match on it as riscv can do both in-order and unspecified order. OK, so expand is not actually a problem because no current gimple generates such things directly; got it. The scatter_store patterns can do as required. Also, since scatter operations use fixed strides the question of in-order, or not, is actually a non-issue even on GCN so we could set the flag safely. As for the recog issue, can predicates not take care of that? (define_predicate "riscv_in_order_vector_mem" (and (match_operand 0 "memory_operand") (match_test "MEM_IN_ORDER_WRITE_P (op)"))) Andrew > > Richard > >> >> If we're just assuming in-order by default, the code produced would actually be unsuitable for GCN. Except it isn't, of course, because autovectorization (and OpenMP parallel, etc) require that the loop iterations are independent, and therefore we choose to assume (rightly or wrongly) that using the writes that we have are safe. >> >> But GCN would have to somehow go though and remove all those flags, or else whatever RTL optimizer it is that cares about such things would be getting misinformed. >> >> Andrew
> Also, since scatter operations use fixed strides the question of > in-order, or not, is actually a non-issue even on GCN so we could set > the flag safely. Consider stride 0 and stride < element size, though. I'm currently thinking of how/where to add the proper versioning decision for that.
>> Also, since scatter operations use fixed strides the question of >> in-order, or not, is actually a non-issue even on GCN so we could set >> the flag safely. > > Consider stride 0 and stride < element size, though. I'm currently > thinking of how/where to add the proper versioning decision for that. Ah, that might only be an issue for riscv where we allow byte strides. For a regular scatter with at least element stride, this would be ok I guess.
On Wed, Jul 29, 2026 at 10:38 AM Robin Dapp <rdapp.gcc@gmail.com> wrote: > > >> Also, since scatter operations use fixed strides the question of > >> in-order, or not, is actually a non-issue even on GCN so we could set > >> the flag safely. > > > > Consider stride 0 and stride < element size, though. I'm currently > > thinking of how/where to add the proper versioning decision for that. > > Ah, that might only be an issue for riscv where we allow byte strides. > For a regular scatter with at least element stride, this would be ok I > guess. scatter is not fixed stride but base address + vector of offsets where offsets need not be distinct. Richard. > -- > Regards > Robin >
On 29/07/2026 09:36, Robin Dapp wrote: >> Also, since scatter operations use fixed strides the question of >> in-order, or not, is actually a non-issue even on GCN so we could set >> the flag safely. > > Consider stride 0 and stride < element size, though. I'm currently > thinking of how/where to add the proper versioning decision for that. I'm generally of the opinion that the compiler should not compromise the speed of well written code to cover whatever abomination somehow manages to convince the autovectorizer to generate zero stride lengths. My interest is in OpenMP/OpenACC where the multithreading already destroyed all notion of left-to-rightness that the vectorizer tries so hard to preserve. In these cases, the end-user has declared and promised that the loop iterations are independent, and if it turns out that's not the case, then that's on them. However, if riscv has the instructions and hardware to handle that case, would it not naturally fall to the "scatter_store" expander to handle these cases? This feeling like a back-end decision, to me. Or, are you thinking of versioning it in gimple, somehow? I assume this would require knowing how the backend instruction handles the writes... would the plan be to never ask the backend to do something in-order if it can't promise that? Andrew
On Wed, Jul 29, 2026 at 10:53 AM Andrew Stubbs <ams@baylibre.com> wrote: > > On 29/07/2026 09:36, Robin Dapp wrote: > >> Also, since scatter operations use fixed strides the question of > >> in-order, or not, is actually a non-issue even on GCN so we could set > >> the flag safely. > > > > Consider stride 0 and stride < element size, though. I'm currently > > thinking of how/where to add the proper versioning decision for that. > > I'm generally of the opinion that the compiler should not compromise the > speed of well written code to cover whatever abomination somehow manages > to convince the autovectorizer to generate zero stride lengths. > > My interest is in OpenMP/OpenACC where the multithreading already > destroyed all notion of left-to-rightness that the vectorizer tries so > hard to preserve. In these cases, the end-user has declared and promised > that the loop iterations are independent, and if it turns out that's not > the case, then that's on them. > > However, if riscv has the instructions and hardware to handle that case, > would it not naturally fall to the "scatter_store" expander to handle > these cases? This feeling like a back-end decision, to me. > > Or, are you thinking of versioning it in gimple, somehow? I assume this > would require knowing how the backend instruction handles the writes... > would the plan be to never ask the backend to do something in-order if > it can't promise that? It's when the vectorizer vectorizes a store with an invaraint but not known non-zero stride or when there a scatter pattern for (int i ...) a[b[i]] = ...; where we cannot obviously "prove" there's no dependence between a[b[0]] and a[b[1]] that we can either not vectorize or have a left-to-right scatter operation. For strided stores we can version on the invariant stride being non-zero (or again rely on left-to-right, which riscv supports) Sure if the user writes a #pragma ivdep or similar openacc/openmp annotation we do not have to do dependence checking and are free to use unordered variants. Richard. > > Andrew
> I'm generally of the opinion that the compiler should not compromise > the speed of well written code to cover whatever abomination somehow > manages to convince the autovectorizer to generate zero stride > lengths. Just suppose we have a (runtime) variable stride like in x264. Here, as well as with general scatter (just an array of offset from a base address) we have no easy way of knowing whether the access is not overlapping. Thus, we need to conservatively assume overlap takes place and basically always have to assume the mem is "left to right". Even if the stride is statically known and large there can be overlap in case we cannot analyze the dataref. > My interest is in OpenMP/OpenACC where the multithreading already > destroyed all notion of left-to-rightness that the vectorizer tries so > hard to preserve. In these cases, the end-user has declared and > promised that the loop iterations are independent, and if it turns out > that's not the case, then that's on them. > > However, if riscv has the instructions and hardware to handle that case, > would it not naturally fall to the "scatter_store" expander to handle > these cases? This feeling like a back-end decision, to me. > Or, are you thinking of versioning it in gimple, somehow? I assume > this would require knowing how the backend instruction handles the > writes... would the plan be to never ask the backend to do something > in-order if it can't promise that? Yes, gimple/vect and I'm still undecided how to best ask the backend. Unfortunately, riscv's strided store only does unordered accesses and cannot switch like our scatters. If we always fell back to ordered scatters, it would likely impact performance (depends on the uarch of course) while versioning for stride > element size would allow us to always generate strided stores which are potentially faster.
Andrew Stubbs <ams@baylibre.com> writes: > On 28/07/2026 17:21, Richard Sandiford wrote: >> Andrew Stubbs <ams@baylibre.com> writes: >>> On 28/07/2026 12:54, Richard Biener wrote: >>>> [...] >>>> Just to add that (mem:<vector> ..) with unordered semantics ties us >>>> to that >>>> unless we want to have a flag on the mem to have left-to-right semantics. >>>> Given it in theory should be made to fit gather/scatter modelling >>>> (ignoring >>>> the masking representational issue). So I'd like at least that >>>> thought out, >>>> if not documented and implemented (having the flag and printing it). >> >> Agreed FWIW. >> >> I think it would be good to think about the masking issue too, given >> Robin's parallel discussion about having a better representation of >> predication. Again, just in terms of having a plausible approach >> thought out, rather than being implemented in the first version. >> >>> I believe the /i and /s flags are available, if we should choose to use >>> them. >>> >>> Would a target hook not be sufficient though? These things are likely to >>> be true always or never, for any given mode, on most architectures. >>> >>> Better even, as such flags are somewhat likely to "get lost" in all the >>> random places that manipulate MEM. >> >> Please don't use a hook! :) IMO RTL semantics should stand on their own >> as far as possible. I realise there are exceptions, like STORE_FLAG_VALUE >> and SHIFT_COUNT_TRUNCATED, but even there, I think it would have been >> better to make the RTL operators self-descriptive and use the macros >> to control which operator is generated. >> >> Making SHIFT_COUNT_TRUNCATED apply to all shift rtxes has been a problem >> in the past and using a hook here might end up the same way. > > OK, let's say MEM_IN_ORDER_WRITE with /i then? If the flag is not > present then the order is undefined. It could work the other way around, > but this seemed to fit nicer with "i". I'm not sure it should be MEM_IN_ORDER_WRITE vs not. That seems more like a property of the operation, rather than a property of the mem object itself. Instead I think the useful information is "guaranteed indepenent addresses" vs not, where "independent" means "not overlapping". As discussed downthread, we'd have to assume that addresses might overlap unless we have specific information to the contrary, so I think "independent" should be 1 and the default/conservative "possibly overlapping" should be 0. Then we could define, for now, that setting a mem whose addresses might overlap is done left-to-right, as a scatter. Thanks, Richard
On 29/07/2026 09:52, Richard Biener wrote: > On Wed, Jul 29, 2026 at 10:38 AM Robin Dapp <rdapp.gcc@gmail.com> wrote: >> >>>> Also, since scatter operations use fixed strides the question of >>>> in-order, or not, is actually a non-issue even on GCN so we could set >>>> the flag safely. >>> >>> Consider stride 0 and stride < element size, though. I'm currently >>> thinking of how/where to add the proper versioning decision for that. >> >> Ah, that might only be an issue for riscv where we allow byte strides. >> For a regular scatter with at least element stride, this would be ok I >> guess. > > scatter is not fixed stride but base address + vector of offsets where > offsets need not be distinct. Sorry, I always forget that it's used primarily for fixed stride accesses, but not actually limited to that. Andrew
On 29/07/2026 10:54, Richard Sandiford wrote: > Andrew Stubbs <ams@baylibre.com> writes: >> On 28/07/2026 17:21, Richard Sandiford wrote: >>> Andrew Stubbs <ams@baylibre.com> writes: >>>> On 28/07/2026 12:54, Richard Biener wrote: >>>>> [...] >>>>> Just to add that (mem:<vector> ..) with unordered semantics ties us >>>>> to that >>>>> unless we want to have a flag on the mem to have left-to-right semantics. >>>>> Given it in theory should be made to fit gather/scatter modelling >>>>> (ignoring >>>>> the masking representational issue). So I'd like at least that >>>>> thought out, >>>>> if not documented and implemented (having the flag and printing it). >>> >>> Agreed FWIW. >>> >>> I think it would be good to think about the masking issue too, given >>> Robin's parallel discussion about having a better representation of >>> predication. Again, just in terms of having a plausible approach >>> thought out, rather than being implemented in the first version. >>> >>>> I believe the /i and /s flags are available, if we should choose to use >>>> them. >>>> >>>> Would a target hook not be sufficient though? These things are likely to >>>> be true always or never, for any given mode, on most architectures. >>>> >>>> Better even, as such flags are somewhat likely to "get lost" in all the >>>> random places that manipulate MEM. >>> >>> Please don't use a hook! :) IMO RTL semantics should stand on their own >>> as far as possible. I realise there are exceptions, like STORE_FLAG_VALUE >>> and SHIFT_COUNT_TRUNCATED, but even there, I think it would have been >>> better to make the RTL operators self-descriptive and use the macros >>> to control which operator is generated. >>> >>> Making SHIFT_COUNT_TRUNCATED apply to all shift rtxes has been a problem >>> in the past and using a hook here might end up the same way. >> >> OK, let's say MEM_IN_ORDER_WRITE with /i then? If the flag is not >> present then the order is undefined. It could work the other way around, >> but this seemed to fit nicer with "i". > > I'm not sure it should be MEM_IN_ORDER_WRITE vs not. That seems more > like a property of the operation, rather than a property of the mem > object itself. > > Instead I think the useful information is "guaranteed indepenent addresses" > vs not, where "independent" means "not overlapping". As discussed downthread, > we'd have to assume that addresses might overlap unless we have specific > information to the contrary, so I think "independent" should be 1 and the > default/conservative "possibly overlapping" should be 0. > > Then we could define, for now, that setting a mem whose addresses might > overlap is done left-to-right, as a scatter. Agreed, MEM_INDEPENDENT works too, and still fits /i neatly. However, this implies that there might be multiple ways to handle non-independent MEMs, and I think that's not true: it really does have to be in-order or nothing. Anyway, this matters little to me. I'm happy to specify whichever. It'll be trivial to set the flag in my code, and only targets that accept vectors as "legitimate addresses" will be affected, which means only GCN to start. Andrew