[clang] [llvm] [X86] Fix LowerFunnelShift crash when folding yields BUILD_VECTOR (PR #233070)
Muhammad Mahdi Amirpour via cfe-commits
cfe-commits at lists.llvm.org
Sat Oct 17 04:24:48 PDT 2026
https://github.com/m-amirpour updated https://github.com/llvm/llvm-project/pull/233070
>From 6a88d0e980d3605297592a17ef2b5cfad137db69 Mon Sep 17 00:00:00 2001
From: m-amirpour <ampr.mhd at gmail.com>
Date: Fri, 16 Oct 2026 17:09:03 +0330
Subject: [PATCH 1/2] [clang] Add regression test for GH205000
---
clang/test/SemaCXX/cxx2c-fold-exprs.cpp | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/clang/test/SemaCXX/cxx2c-fold-exprs.cpp b/clang/test/SemaCXX/cxx2c-fold-exprs.cpp
index f0819ed04881b3..0778ed7fe66372 100644
--- a/clang/test/SemaCXX/cxx2c-fold-exprs.cpp
+++ b/clang/test/SemaCXX/cxx2c-fold-exprs.cpp
@@ -752,3 +752,18 @@ static_assert(count == 2);
}
+namespace GH205000 {
+
+template <int N>
+struct StringLiteral {
+ constexpr StringLiteral(const auto... c)
+ requires (__is_same(decltype(c), const char) && ...) {}
+ constexpr StringLiteral(const char (&s)[N]) {}
+};
+
+template <StringLiteral... fields>
+struct Lit {};
+
+using Unit = Lit<"a">;
+
+}
>From ad41cf14b096a1dda89af6c801367fe8218189b4 Mon Sep 17 00:00:00 2001
From: m-amirpour <ampr.mhd at gmail.com>
Date: Sat, 17 Oct 2026 14:48:12 +0330
Subject: [PATCH 2/2] [X86] Fix LowerFunnelShift crash when folding yields
BUILD_VECTOR
LowerFunnelShift's pre-AVX2 256-bit split path calls
DAG.getNode(FSHL/FSHR, ...) and then splitVectorOp on the result. When all
operands are constants -- e.g. ucmp(x, x) expanded to a zero vector by the
vector legalizer -- getNode constant-folds the funnel shift into a
BUILD_VECTOR. splitVectorOp then treats the 8 scalar BUILD_VECTOR operands
as sub-vectors, producing a malformed v4i32 BUILD_VECTOR with 8 operands:
an assertion failure ("Incorrect element count in BUILD_VECTOR!") in
asserts builds, and heap corruption in Release builds.
Bail out to the generic path when the node was constant-folded.
Fixes https://github.com/llvm/llvm-project/issues/233063
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 9 ++++++++
.../X86/funnel-shift-avx-constant-fold.ll | 22 +++++++++++++++++++
2 files changed, 31 insertions(+)
create mode 100644 llvm/test/CodeGen/X86/funnel-shift-avx-constant-fold.ll
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 416761793904f9..d5ec8d9f3704b6 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -32290,7 +32290,16 @@ static SDValue LowerFunnelShift(SDValue Op, const X86Subtarget &Subtarget,
(VT.is512BitVector() && !Subtarget.useBWIRegs() &&
EltSizeInBits < 32)) {
// Pre-mask the amount modulo using the wider vector.
+ unsigned OrigOpc = Op.getOpcode();
Op = DAG.getNode(Op.getOpcode(), DL, VT, Op0, Op1, AmtMod);
+
+ // If constant folding turned the funnel shift into a BUILD_VECTOR (e.g.
+ // ucmp(x, x) was expanded to a zero vector by the legalizer), don't try
+ // to split a non-funnel-shift node: its operands are scalars, not
+ // sub-vectors. Let the generic legalizer handle it instead.
+ if (Op.getOpcode() != OrigOpc)
+ return Op;
+
return splitVectorOp(Op, DAG, DL);
}
diff --git a/llvm/test/CodeGen/X86/funnel-shift-avx-constant-fold.ll b/llvm/test/CodeGen/X86/funnel-shift-avx-constant-fold.ll
new file mode 100644
index 00000000000000..db5cceeb9faed6
--- /dev/null
+++ b/llvm/test/CodeGen/X86/funnel-shift-avx-constant-fold.ll
@@ -0,0 +1,22 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx | FileCheck %s
+
+; Regression test for https://github.com/llvm/llvm-project/issues/233063
+; LowerFunnelShift's pre-AVX2 256-bit split path called splitVectorOp on a
+; node that constant-folded into a BUILD_VECTOR, producing a malformed
+; v4i32 BUILD_VECTOR with 8 scalar operands (assert, or heap corruption in
+; Release builds).
+
+define <8 x i32> @fshr_constant_fold(<8 x i32> %x) {
+; CHECK-LABEL: fshr_constant_fold:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vmovaps {{.*#+}} ymm0 = [8,8,24,16,40,24,56,32]
+; CHECK-NEXT: retq
+ %v0 = call <8 x i32> @llvm.ucmp.v8i32.v8i32(<8 x i32> %x, <8 x i32> %x)
+ %v1 = call <8 x i32> @llvm.fshr.v8i32(<8 x i32> %v0, <8 x i32> <i32 16, i32 32, i32 48, i32 64, i32 80, i32 96, i32 112, i32 128>,
+ <8 x i32> <i32 1, i32 2, i32 1, i32 2, i32 1, i32 2, i32 1, i32 2>)
+ ret <8 x i32> %v1
+}
+
+declare <8 x i32> @llvm.ucmp.v8i32.v8i32(<8 x i32>, <8 x i32>)
+declare <8 x i32> @llvm.fshr.v8i32(<8 x i32>, <8 x i32>, <8 x i32>)
More information about the cfe-commits
mailing list