[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