[llvm] [Hexagon] Fix SplitVectors crash in HVX type legalization (PR #181377)
Brian Cain via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 13 12:10:39 PST 2026
https://github.com/androm3da updated https://github.com/llvm/llvm-project/pull/181377
>From 5055aa96f61961c8e5164f9ce81fba431d143dd1 Mon Sep 17 00:00:00 2001
From: Brian Cain <brian.cain at oss.qualcomm.com>
Date: Thu, 12 Feb 2026 22:10:26 -0800
Subject: [PATCH] [Hexagon] Fix SplitVectors crash in HVX type legalization
When LegalizeHvxResize splits a multi-step TL_EXTEND (e.g., v128i32
from v128i8, which is i8->i32), SplitVectorOp halves both input and
output types. This creates operand types that are half the HVX vector
width (e.g., v64i8 = 512 bits on 128-byte HVX), which are not legal
HVX types. These sub-HVX intermediate types confuse the DAG type
legalizer's map tracking, causing "Unprocessed value in a map!
SplitVectors" assertions with EXPENSIVE_CHECKS or
-enable-legalize-types-checking.
Fix by first expanding multi-step TL_EXTEND/TL_TRUNCATE operations
into a chain of single-step operations via ExpandHvxResizeIntoSteps
before splitting. Each single-step operation (e.g., i16->i32) can be
safely split because halving its operand type produces a legal HVX
type (e.g., v64i16 = HVX single vector).
---
.../Target/Hexagon/HexagonISelLoweringHVX.cpp | 9 ++++++++
.../CodeGen/Hexagon/hvx-zext-split-check.ll | 23 +++++++++++++++++++
2 files changed, 32 insertions(+)
create mode 100644 llvm/test/CodeGen/Hexagon/hvx-zext-split-check.ll
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
index b1181dfa13a10..4eefec95d09d2 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
@@ -3785,6 +3785,15 @@ HexagonTargetLowering::LegalizeHvxResize(SDValue Op, SelectionDAG &DAG) const {
SDValue T = ExpandHvxResizeIntoSteps(S, DAG);
return extractSubvector(T, typeLegalize(ResTy, DAG), 0, DAG);
} else if (shouldSplitToHvx(InpWidth < ResWidth ? ResTy : InpTy, DAG)) {
+ // For multi-step extends/truncates (e.g., i8->i32), expand into
+ // single-step operations first. Splitting a multi-step TL_EXTEND
+ // would halve the operand type to a sub-HVX size (e.g., v128i8 ->
+ // v64i8), creating illegal types that cause issues in the type
+ // legalizer's map tracking. Single-step operations (e.g., i16->i32)
+ // are safe to split because their halved operand types remain legal.
+ SDValue T = ExpandHvxResizeIntoSteps(Op, DAG);
+ if (T != Op)
+ return T;
return opJoin(SplitVectorOp(Op, DAG), SDLoc(Op), DAG);
} else {
assert(isTypeLegal(InpTy) && isTypeLegal(ResTy));
diff --git a/llvm/test/CodeGen/Hexagon/hvx-zext-split-check.ll b/llvm/test/CodeGen/Hexagon/hvx-zext-split-check.ll
new file mode 100644
index 0000000000000..b8f2bf672ab96
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/hvx-zext-split-check.ll
@@ -0,0 +1,23 @@
+; RUN: llc -mtriple=hexagon -mcpu=hexagonv73 -mattr=+hvxv73,+hvx-length128b \
+; RUN: -enable-legalize-types-checking < %s | FileCheck %s
+;
+; Check that HVX zero-extend operations that require splitting compile
+; correctly. The bug was that multi-step TL_EXTEND operations (e.g., i8->i32)
+; were split directly, creating sub-HVX operand types (v64i8) that confused
+; the legalizer's map tracking. The fix expands multi-step extends into
+; single steps first.
+
+target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048"
+target triple = "hexagon-unknown-linux-musl"
+
+; CHECK-LABEL: test_zext_split:
+; CHECK-DAG: vunpack
+; CHECK-DAG: vadd
+; CHECK: jumpr r31
+define fastcc <32 x i32> @test_zext_split(<32 x i8> %a, <32 x i8> %b) {
+entry:
+ %ext_a = zext <32 x i8> %a to <32 x i32>
+ %ext_b = zext <32 x i8> %b to <32 x i32>
+ %sum = add <32 x i32> %ext_a, %ext_b
+ ret <32 x i32> %sum
+}
More information about the llvm-commits
mailing list