[llvm] [SLP][NFC]Add a test with missed vectorization, NFC (PR #222141)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 8 13:55:54 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Alexey Bataev (alexey-bataev)
<details>
<summary>Changes</summary>
---
Full diff: https://github.com/llvm/llvm-project/pull/222141.diff
1 Files Affected:
- (added) llvm/test/Transforms/SLPVectorizer/AArch64/splat-gather-subtree-drop.ll (+144)
``````````diff
diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/splat-gather-subtree-drop.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/splat-gather-subtree-drop.ll
new file mode 100644
index 0000000000000..c6677935dacda
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/AArch64/splat-gather-subtree-drop.ll
@@ -0,0 +1,144 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes=slp-vectorizer -mtriple=aarch64-unknown-linux-gnu -mcpu=neoverse-v2 < %s | FileCheck %s
+
+; The splat subtree for the zexts is not worth keeping: the splat gathers are
+; cheaper as plain insertion sequences, and the paired arithmetic must still
+; be vectorized.
+
+define i32 @test1(ptr %p, ptr %q, i32 %seed) {
+; CHECK-LABEL: define i32 @test1(
+; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i32 [[SEED:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[V0:%.*]] = load i8, ptr [[P]], align 1
+; CHECK-NEXT: [[V1:%.*]] = zext i8 [[V0]] to i32
+; CHECK-NEXT: [[V2:%.*]] = add nuw nsw i32 [[V1]], 1
+; CHECK-NEXT: [[V3:%.*]] = load i8, ptr [[Q]], align 1
+; CHECK-NEXT: [[V4:%.*]] = zext i8 [[V3]] to i32
+; CHECK-NEXT: [[V5:%.*]] = or i32 [[V2]], [[V4]]
+; CHECK-NEXT: [[V6:%.*]] = and i32 [[V4]], 1
+; CHECK-NEXT: [[V7:%.*]] = add nuw nsw i32 [[V6]], 1
+; CHECK-NEXT: [[V8:%.*]] = xor i32 [[V7]], 1
+; CHECK-NEXT: [[V9:%.*]] = add nuw nsw i32 [[V5]], 1
+; CHECK-NEXT: [[V10:%.*]] = and i32 [[V5]], 1
+; CHECK-NEXT: [[V11:%.*]] = xor i32 [[V9]], [[V10]]
+; CHECK-NEXT: [[V12:%.*]] = or i32 [[V8]], [[V11]]
+; CHECK-NEXT: [[V13:%.*]] = add nsw i32 [[V1]], -2
+; CHECK-NEXT: [[V14:%.*]] = or i32 [[V13]], [[V4]]
+; CHECK-NEXT: [[V15:%.*]] = and i32 [[SEED]], 1
+; CHECK-NEXT: [[V16:%.*]] = add nuw nsw i32 [[V15]], 1
+; CHECK-NEXT: [[V17:%.*]] = xor i32 [[V16]], 1
+; CHECK-NEXT: [[V18:%.*]] = add nsw i32 [[V14]], 1
+; CHECK-NEXT: [[V19:%.*]] = and i32 [[V14]], 1
+; CHECK-NEXT: [[V20:%.*]] = xor i32 [[V18]], [[V19]]
+; CHECK-NEXT: [[V21:%.*]] = or i32 [[V17]], [[V20]]
+; CHECK-NEXT: [[V22:%.*]] = or i32 [[V12]], [[V21]]
+; CHECK-NEXT: ret i32 [[V22]]
+;
+entry:
+ %v0 = load i8, ptr %p, align 1
+ %v1 = zext i8 %v0 to i32
+ %v2 = add nuw nsw i32 %v1, 1
+ %v3 = load i8, ptr %q, align 1
+ %v4 = zext i8 %v3 to i32
+ %v5 = or i32 %v2, %v4
+ %v6 = and i32 %v4, 1
+ %v7 = add nuw nsw i32 %v6, 1
+ %v8 = xor i32 %v7, 1
+ %v9 = add nuw nsw i32 %v5, 1
+ %v10 = and i32 %v5, 1
+ %v11 = xor i32 %v9, %v10
+ %v12 = or i32 %v8, %v11
+ %v13 = add nsw i32 %v1, -2
+ %v14 = or i32 %v13, %v4
+ %v15 = and i32 %seed, 1
+ %v16 = add nuw nsw i32 %v15, 1
+ %v17 = xor i32 %v16, 1
+ %v18 = add nsw i32 %v14, 1
+ %v19 = and i32 %v14, 1
+ %v20 = xor i32 %v18, %v19
+ %v21 = or i32 %v17, %v20
+ %v22 = or i32 %v12, %v21
+ ret i32 %v22
+}
+
+; The splat subtree for %s0/%s1 is trimmed away, but that must not make the
+; revert comparison keep the trimmed alt-shuffle node: the paired arithmetic
+; must still be vectorized.
+
+define void @test2(ptr %out, ptr %in, i64 %n, double %a0, double %a1, double %a2, double %a3, double %a10, double %a11) {
+; CHECK-LABEL: define void @test2(
+; CHECK-SAME: ptr [[OUT:%.*]], ptr [[IN:%.*]], i64 [[N:%.*]], double [[A0:%.*]], double [[A1:%.*]], double [[A2:%.*]], double [[A3:%.*]], double [[A10:%.*]], double [[A11:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: br label %[[BODY:.*]]
+; CHECK: [[BODY]]:
+; CHECK-NEXT: [[I:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[NEXT:%.*]], %[[BODY]] ]
+; CHECK-NEXT: [[X0:%.*]] = load double, ptr [[IN]], align 8
+; CHECK-NEXT: [[P1:%.*]] = getelementptr double, ptr [[IN]], i64 1
+; CHECK-NEXT: [[X1:%.*]] = load double, ptr [[P1]], align 8
+; CHECK-NEXT: [[P2:%.*]] = getelementptr double, ptr [[IN]], i64 2
+; CHECK-NEXT: [[X2:%.*]] = load double, ptr [[P2]], align 8
+; CHECK-NEXT: [[P3:%.*]] = getelementptr double, ptr [[IN]], i64 3
+; CHECK-NEXT: [[X3:%.*]] = load double, ptr [[P3]], align 8
+; CHECK-NEXT: [[S0:%.*]] = fdiv double [[A0]], [[A1]]
+; CHECK-NEXT: [[S1:%.*]] = fsub double [[A2]], [[A3]]
+; CHECK-NEXT: [[V0_0:%.*]] = fadd double [[X0]], [[A10]]
+; CHECK-NEXT: [[V1_0:%.*]] = fsub double [[X1]], [[A11]]
+; CHECK-NEXT: [[V0_1:%.*]] = fsub double [[V0_0]], [[S1]]
+; CHECK-NEXT: [[V1_1:%.*]] = fsub double [[V1_0]], [[S1]]
+; CHECK-NEXT: [[V0_2:%.*]] = fsub double [[V0_1]], [[S0]]
+; CHECK-NEXT: [[V1_2:%.*]] = fsub double [[V1_1]], [[S0]]
+; CHECK-NEXT: [[V0_3:%.*]] = fadd double [[V0_2]], [[A10]]
+; CHECK-NEXT: [[V1_3:%.*]] = fadd double [[V1_2]], [[A11]]
+; CHECK-NEXT: [[V0_4:%.*]] = fsub double [[V0_3]], [[S0]]
+; CHECK-NEXT: [[V1_4:%.*]] = fsub double [[V1_3]], [[S0]]
+; CHECK-NEXT: [[V0_5:%.*]] = fadd double [[V0_4]], [[S0]]
+; CHECK-NEXT: [[V1_5:%.*]] = fadd double [[V1_4]], [[S0]]
+; CHECK-NEXT: [[V0_6:%.*]] = fsub double [[V0_5]], [[X2]]
+; CHECK-NEXT: [[V1_6:%.*]] = fsub double [[V1_5]], [[X3]]
+; CHECK-NEXT: store double [[V0_6]], ptr [[OUT]], align 8
+; CHECK-NEXT: [[O1:%.*]] = getelementptr double, ptr [[OUT]], i64 1
+; CHECK-NEXT: store double [[V1_6]], ptr [[O1]], align 8
+; CHECK-NEXT: [[NEXT]] = add i64 [[I]], 1
+; CHECK-NEXT: [[MORE:%.*]] = icmp ult i64 [[NEXT]], [[N]]
+; CHECK-NEXT: br i1 [[MORE]], label %[[BODY]], label %[[EXIT:.*]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: ret void
+;
+entry:
+ br label %body
+
+body:
+ %i = phi i64 [ 0, %entry ], [ %next, %body ]
+ %x0 = load double, ptr %in, align 8
+ %p1 = getelementptr double, ptr %in, i64 1
+ %x1 = load double, ptr %p1, align 8
+ %p2 = getelementptr double, ptr %in, i64 2
+ %x2 = load double, ptr %p2, align 8
+ %p3 = getelementptr double, ptr %in, i64 3
+ %x3 = load double, ptr %p3, align 8
+ %s0 = fdiv double %a0, %a1
+ %s1 = fsub double %a2, %a3
+ %v0_0 = fadd double %x0, %a10
+ %v1_0 = fsub double %x1, %a11
+ %v0_1 = fsub double %v0_0, %s1
+ %v1_1 = fsub double %v1_0, %s1
+ %v0_2 = fsub double %v0_1, %s0
+ %v1_2 = fsub double %v1_1, %s0
+ %v0_3 = fadd double %v0_2, %a10
+ %v1_3 = fadd double %v1_2, %a11
+ %v0_4 = fsub double %v0_3, %s0
+ %v1_4 = fsub double %v1_3, %s0
+ %v0_5 = fadd double %v0_4, %s0
+ %v1_5 = fadd double %v1_4, %s0
+ %v0_6 = fsub double %v0_5, %x2
+ %v1_6 = fsub double %v1_5, %x3
+ store double %v0_6, ptr %out, align 8
+ %o1 = getelementptr double, ptr %out, i64 1
+ store double %v1_6, ptr %o1, align 8
+ %next = add i64 %i, 1
+ %more = icmp ult i64 %next, %n
+ br i1 %more, label %body, label %exit
+
+exit:
+ ret void
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/222141
More information about the llvm-commits
mailing list