[llvm] SelectionDAG: Fix widening of vector addrspacecast results (PR #217898)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 21 05:23:19 PDT 2026
https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/217898
WidenVecRes_ADDRSPACECAST unconditionally called GetWidenedVector on the
source operand, which asserts the operand is itself in the widened-vector
map. When the source vector type does not require widening (e.g. a
<5 x ptr addrspace(3)> cast to <5 x ptr>, where the source is padded
rather than widened), this asserted or crashed. Handle the non-widened
source by padding it up to the widened element count instead.
Co-authored-by: Claude (Claude-Opus-4.8) <noreply at anthropic.com>
>From 68d2f9700ff1a982874bd1e2acb85cd7eea14c94 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Fri, 21 Aug 2026 14:17:02 +0200
Subject: [PATCH] SelectionDAG: Fix widening of vector addrspacecast results
WidenVecRes_ADDRSPACECAST unconditionally called GetWidenedVector on the
source operand, which asserts the operand is itself in the widened-vector
map. When the source vector type does not require widening (e.g. a
<5 x ptr addrspace(3)> cast to <5 x ptr>, where the source is padded
rather than widened), this asserted or crashed. Handle the non-widened
source by padding it up to the widened element count instead.
Co-authored-by: Claude (Claude-Opus-4.8) <noreply at anthropic.com>
---
.../SelectionDAG/LegalizeVectorTypes.cpp | 18 +++++-
.../AMDGPU/addrspacecast-widen-vector.ll | 64 +++++++++++++++++++
2 files changed, 80 insertions(+), 2 deletions(-)
create mode 100644 llvm/test/CodeGen/AMDGPU/addrspacecast-widen-vector.ll
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
index 3417c9734af3b..8a2cf2fd81527 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
@@ -6494,11 +6494,25 @@ SDValue DAGTypeLegalizer::WidenVecRes_MERGE_VALUES(SDNode *N, unsigned ResNo) {
}
SDValue DAGTypeLegalizer::WidenVecRes_ADDRSPACECAST(SDNode *N) {
+ SDLoc DL(N);
EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
- SDValue InOp = GetWidenedVector(N->getOperand(0));
+ ElementCount WidenEC = WidenVT.getVectorElementCount();
auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
- return DAG.getAddrSpaceCast(SDLoc(N), WidenVT, InOp,
+ // The source has the same number of elements as the result, so widen it to
+ // match WidenVT. It only lives in the widened-vector map if it is itself
+ // widened; otherwise pad it up to the widened element count.
+ SDValue InOp = N->getOperand(0);
+ EVT InVT = InOp.getValueType();
+ if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
+ InOp = GetWidenedVector(InOp);
+ } else {
+ EVT InWidenVT = EVT::getVectorVT(*DAG.getContext(),
+ InVT.getVectorElementType(), WidenEC);
+ InOp = DAG.getInsertSubvector(DL, DAG.getPOISON(InWidenVT), InOp, 0);
+ }
+
+ return DAG.getAddrSpaceCast(DL, WidenVT, InOp,
AddrSpaceCastN->getSrcAddressSpace(),
AddrSpaceCastN->getDestAddressSpace());
}
diff --git a/llvm/test/CodeGen/AMDGPU/addrspacecast-widen-vector.ll b/llvm/test/CodeGen/AMDGPU/addrspacecast-widen-vector.ll
new file mode 100644
index 0000000000000..f9029e4f5ead3
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/addrspacecast-widen-vector.ll
@@ -0,0 +1,64 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -global-isel=0 -mtriple=amdgpu9.00-amd-amdhsa < %s | FileCheck --check-prefixes=CHECK,DAGISEL %s
+; RUN: llc -global-isel=1 -mtriple=amdgpu9.00-amd-amdhsa < %s | FileCheck --check-prefixes=CHECK,GISEL %s
+
+; A vector addrspacecast whose result type requires widening (v5 rounds up to
+; v8) must not crash the type legalizer.
+
+define <5 x ptr> @local_to_flat_widen(<5 x ptr addrspace(3)> %ptr) {
+; DAGISEL-LABEL: local_to_flat_widen:
+; DAGISEL: ; %bb.0:
+; DAGISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; DAGISEL-NEXT: s_mov_b64 s[4:5], src_shared_base
+; DAGISEL-NEXT: v_cmp_ne_u32_e32 vcc, -1, v0
+; DAGISEL-NEXT: v_mov_b32_e32 v9, s5
+; DAGISEL-NEXT: v_cndmask_b32_e32 v0, 0, v0, vcc
+; DAGISEL-NEXT: v_cndmask_b32_e32 v13, 0, v9, vcc
+; DAGISEL-NEXT: v_cmp_ne_u32_e32 vcc, -1, v1
+; DAGISEL-NEXT: v_cndmask_b32_e32 v10, 0, v1, vcc
+; DAGISEL-NEXT: v_cndmask_b32_e32 v11, 0, v9, vcc
+; DAGISEL-NEXT: v_cmp_ne_u32_e32 vcc, -1, v2
+; DAGISEL-NEXT: v_cndmask_b32_e32 v12, 0, v2, vcc
+; DAGISEL-NEXT: v_cndmask_b32_e32 v5, 0, v9, vcc
+; DAGISEL-NEXT: v_cmp_ne_u32_e32 vcc, -1, v3
+; DAGISEL-NEXT: v_cndmask_b32_e32 v6, 0, v3, vcc
+; DAGISEL-NEXT: v_cndmask_b32_e32 v7, 0, v9, vcc
+; DAGISEL-NEXT: v_cmp_ne_u32_e32 vcc, -1, v4
+; DAGISEL-NEXT: v_cndmask_b32_e32 v8, 0, v4, vcc
+; DAGISEL-NEXT: v_cndmask_b32_e32 v9, 0, v9, vcc
+; DAGISEL-NEXT: v_mov_b32_e32 v1, v13
+; DAGISEL-NEXT: v_mov_b32_e32 v2, v10
+; DAGISEL-NEXT: v_mov_b32_e32 v3, v11
+; DAGISEL-NEXT: v_mov_b32_e32 v4, v12
+; DAGISEL-NEXT: s_setpc_b64 s[30:31]
+;
+; GISEL-LABEL: local_to_flat_widen:
+; GISEL: ; %bb.0:
+; GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GISEL-NEXT: s_mov_b64 s[4:5], src_shared_base
+; GISEL-NEXT: v_mov_b32_e32 v9, s5
+; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, -1, v0
+; GISEL-NEXT: v_cndmask_b32_e32 v0, 0, v0, vcc
+; GISEL-NEXT: v_cndmask_b32_e32 v13, 0, v9, vcc
+; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, -1, v1
+; GISEL-NEXT: v_cndmask_b32_e32 v10, 0, v1, vcc
+; GISEL-NEXT: v_cndmask_b32_e32 v11, 0, v9, vcc
+; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, -1, v2
+; GISEL-NEXT: v_cndmask_b32_e32 v12, 0, v2, vcc
+; GISEL-NEXT: v_cndmask_b32_e32 v5, 0, v9, vcc
+; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, -1, v3
+; GISEL-NEXT: v_cndmask_b32_e32 v6, 0, v3, vcc
+; GISEL-NEXT: v_cndmask_b32_e32 v7, 0, v9, vcc
+; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, -1, v4
+; GISEL-NEXT: v_cndmask_b32_e32 v8, 0, v4, vcc
+; GISEL-NEXT: v_cndmask_b32_e32 v9, 0, v9, vcc
+; GISEL-NEXT: v_mov_b32_e32 v1, v13
+; GISEL-NEXT: v_mov_b32_e32 v2, v10
+; GISEL-NEXT: v_mov_b32_e32 v3, v11
+; GISEL-NEXT: v_mov_b32_e32 v4, v12
+; GISEL-NEXT: s_setpc_b64 s[30:31]
+ %cast = addrspacecast <5 x ptr addrspace(3)> %ptr to <5 x ptr>
+ ret <5 x ptr> %cast
+}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}
More information about the llvm-commits
mailing list