https://github.com/m-amirpour created https://github.com/llvm/llvm-project/pull/233070
Fixes #233063. `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: - **+asserts**: `Assertion 'VT.getVectorNumElements() == (unsigned)NumOps && "Incorrect element count in BUILD_VECTOR!"' failed.` - **Release**: `free(): invalid size` (heap corruption). Bail out to the generic path when the node was constant-folded. ## Test - Reproducer from the issue: `llc -O2 -mattr=+avx crash-min.ll -o /dev/null` - before: assertion / SIGABRT - after: exits 0 - New regression test: `llvm/test/CodeGen/X86/funnel-shift-avx-constant-fold.ll` - `ninja check-llvm-codegen-x86`: 5762 tests, 0 failures (5745 pass, 15 XFAIL, 2 unsupported) - `clang-format`: no changes >From 6a88d0e980d3605297592a17ef2b5cfad137db69 Mon Sep 17 00:00:00 2001 From: m-amirpour <[email protected]> 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 <[email protected]> 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>) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
