[llvm] [SLP][NFC] Add precommit test for dot-product reduction costing (PR #224590)
Madhur Amilkanthwar via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 18 04:06:25 PDT 2026
https://github.com/madhur13490 updated https://github.com/llvm/llvm-project/pull/224590
>From e331efd6d01a6462600556b60a1f1f7cd8c56d2d Mon Sep 17 00:00:00 2001
From: Madhur Amilkanthwar <madhura at nvidia.com>
Date: Thu, 17 Sep 2026 04:13:14 -0700
Subject: [PATCH 1/2] [SLP][NFC] Add precommit test for dot-product reduction
costing
Adds a test for reduce.add(mul(ext, ext)) with and without +dotprod at a threshold between the plain and fused costs. Baseline: both stay scalar; a later change makes the +dotprod case vectorize.
---
.../AArch64/reduce-add-dotprod.ll | 273 ++++++++++++++++++
1 file changed, 273 insertions(+)
create mode 100644 llvm/test/Transforms/SLPVectorizer/AArch64/reduce-add-dotprod.ll
diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/reduce-add-dotprod.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/reduce-add-dotprod.ll
new file mode 100644
index 0000000000000..36d2a0f797280
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/AArch64/reduce-add-dotprod.ll
@@ -0,0 +1,273 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes=slp-vectorizer -slp-threshold=28 -S -mtriple=aarch64 < %s | FileCheck %s
+
+; The reduce.add(mul(ext, ext)) idiom lowers to a single dot-product
+; reduction (UDOT/SDOT) when the target supports it. The threshold is set
+; between the plain reduction cost and the fused dot-product cost so the
+; reduction is profitable only when the dot-product cost applies: the
+; +dotprod function vectorizes, the plain function stays scalar.
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32"
+target triple = "aarch64"
+
+define i32 @mla_v8i8_i32_dotprod(ptr %x, ptr %y) "target-features"="+dotprod" {
+; CHECK-LABEL: @mla_v8i8_i32_dotprod(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[X:%.*]], align 1
+; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[TMP0]] to i32
+; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[Y:%.*]], align 1
+; CHECK-NEXT: [[CONV3:%.*]] = sext i8 [[TMP1]] to i32
+; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[CONV3]], [[CONV]]
+; CHECK-NEXT: [[ARRAYIDX_1:%.*]] = getelementptr inbounds nuw i8, ptr [[X]], i64 1
+; CHECK-NEXT: [[TMP2:%.*]] = load i8, ptr [[ARRAYIDX_1]], align 1
+; CHECK-NEXT: [[CONV_1:%.*]] = sext i8 [[TMP2]] to i32
+; CHECK-NEXT: [[ARRAYIDX2_1:%.*]] = getelementptr inbounds nuw i8, ptr [[Y]], i64 1
+; CHECK-NEXT: [[TMP3:%.*]] = load i8, ptr [[ARRAYIDX2_1]], align 1
+; CHECK-NEXT: [[CONV3_1:%.*]] = sext i8 [[TMP3]] to i32
+; CHECK-NEXT: [[MUL_1:%.*]] = mul nsw i32 [[CONV3_1]], [[CONV_1]]
+; CHECK-NEXT: [[ADD_1:%.*]] = add nsw i32 [[MUL_1]], [[MUL]]
+; CHECK-NEXT: [[ARRAYIDX_2:%.*]] = getelementptr inbounds nuw i8, ptr [[X]], i64 2
+; CHECK-NEXT: [[TMP4:%.*]] = load i8, ptr [[ARRAYIDX_2]], align 1
+; CHECK-NEXT: [[CONV_2:%.*]] = sext i8 [[TMP4]] to i32
+; CHECK-NEXT: [[ARRAYIDX2_2:%.*]] = getelementptr inbounds nuw i8, ptr [[Y]], i64 2
+; CHECK-NEXT: [[TMP16:%.*]] = load i8, ptr [[ARRAYIDX2_2]], align 1
+; CHECK-NEXT: [[CONV3_2:%.*]] = sext i8 [[TMP16]] to i32
+; CHECK-NEXT: [[MUL_2:%.*]] = mul nsw i32 [[CONV3_2]], [[CONV_2]]
+; CHECK-NEXT: [[ADD_2:%.*]] = add nsw i32 [[MUL_2]], [[ADD_1]]
+; CHECK-NEXT: [[ARRAYIDX_3:%.*]] = getelementptr inbounds nuw i8, ptr [[X]], i64 3
+; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[ARRAYIDX_3]], align 1
+; CHECK-NEXT: [[CONV_3:%.*]] = sext i8 [[TMP6]] to i32
+; CHECK-NEXT: [[ARRAYIDX2_3:%.*]] = getelementptr inbounds nuw i8, ptr [[Y]], i64 3
+; CHECK-NEXT: [[TMP7:%.*]] = load i8, ptr [[ARRAYIDX2_3]], align 1
+; CHECK-NEXT: [[CONV3_3:%.*]] = sext i8 [[TMP7]] to i32
+; CHECK-NEXT: [[MUL_3:%.*]] = mul nsw i32 [[CONV3_3]], [[CONV_3]]
+; CHECK-NEXT: [[ADD_3:%.*]] = add nsw i32 [[MUL_3]], [[ADD_2]]
+; CHECK-NEXT: [[ARRAYIDX_4:%.*]] = getelementptr inbounds nuw i8, ptr [[X]], i64 4
+; CHECK-NEXT: [[TMP8:%.*]] = load i8, ptr [[ARRAYIDX_4]], align 1
+; CHECK-NEXT: [[CONV_4:%.*]] = sext i8 [[TMP8]] to i32
+; CHECK-NEXT: [[ARRAYIDX2_4:%.*]] = getelementptr inbounds nuw i8, ptr [[Y]], i64 4
+; CHECK-NEXT: [[TMP9:%.*]] = load i8, ptr [[ARRAYIDX2_4]], align 1
+; CHECK-NEXT: [[CONV3_4:%.*]] = sext i8 [[TMP9]] to i32
+; CHECK-NEXT: [[MUL_4:%.*]] = mul nsw i32 [[CONV3_4]], [[CONV_4]]
+; CHECK-NEXT: [[ADD_4:%.*]] = add nsw i32 [[MUL_4]], [[ADD_3]]
+; CHECK-NEXT: [[ARRAYIDX_5:%.*]] = getelementptr inbounds nuw i8, ptr [[X]], i64 5
+; CHECK-NEXT: [[TMP10:%.*]] = load i8, ptr [[ARRAYIDX_5]], align 1
+; CHECK-NEXT: [[CONV_5:%.*]] = sext i8 [[TMP10]] to i32
+; CHECK-NEXT: [[ARRAYIDX2_5:%.*]] = getelementptr inbounds nuw i8, ptr [[Y]], i64 5
+; CHECK-NEXT: [[TMP11:%.*]] = load i8, ptr [[ARRAYIDX2_5]], align 1
+; CHECK-NEXT: [[CONV3_5:%.*]] = sext i8 [[TMP11]] to i32
+; CHECK-NEXT: [[MUL_5:%.*]] = mul nsw i32 [[CONV3_5]], [[CONV_5]]
+; CHECK-NEXT: [[ADD_5:%.*]] = add nsw i32 [[MUL_5]], [[ADD_4]]
+; CHECK-NEXT: [[ARRAYIDX_6:%.*]] = getelementptr inbounds nuw i8, ptr [[X]], i64 6
+; CHECK-NEXT: [[TMP12:%.*]] = load i8, ptr [[ARRAYIDX_6]], align 1
+; CHECK-NEXT: [[CONV_6:%.*]] = sext i8 [[TMP12]] to i32
+; CHECK-NEXT: [[ARRAYIDX2_6:%.*]] = getelementptr inbounds nuw i8, ptr [[Y]], i64 6
+; CHECK-NEXT: [[TMP13:%.*]] = load i8, ptr [[ARRAYIDX2_6]], align 1
+; CHECK-NEXT: [[CONV3_6:%.*]] = sext i8 [[TMP13]] to i32
+; CHECK-NEXT: [[MUL_6:%.*]] = mul nsw i32 [[CONV3_6]], [[CONV_6]]
+; CHECK-NEXT: [[ADD_6:%.*]] = add nsw i32 [[MUL_6]], [[ADD_5]]
+; CHECK-NEXT: [[ARRAYIDX_7:%.*]] = getelementptr inbounds nuw i8, ptr [[X]], i64 7
+; CHECK-NEXT: [[TMP14:%.*]] = load i8, ptr [[ARRAYIDX_7]], align 1
+; CHECK-NEXT: [[CONV_7:%.*]] = sext i8 [[TMP14]] to i32
+; CHECK-NEXT: [[ARRAYIDX2_7:%.*]] = getelementptr inbounds nuw i8, ptr [[Y]], i64 7
+; CHECK-NEXT: [[TMP15:%.*]] = load i8, ptr [[ARRAYIDX2_7]], align 1
+; CHECK-NEXT: [[CONV3_7:%.*]] = sext i8 [[TMP15]] to i32
+; CHECK-NEXT: [[MUL_7:%.*]] = mul nsw i32 [[CONV3_7]], [[CONV_7]]
+; CHECK-NEXT: [[TMP5:%.*]] = add nsw i32 [[MUL_7]], [[ADD_6]]
+; CHECK-NEXT: ret i32 [[TMP5]]
+;
+entry:
+ %0 = load i8, ptr %x
+ %conv = sext i8 %0 to i32
+ %1 = load i8, ptr %y
+ %conv3 = sext i8 %1 to i32
+ %mul = mul nsw i32 %conv3, %conv
+ %arrayidx.1 = getelementptr inbounds nuw i8, ptr %x, i64 1
+ %2 = load i8, ptr %arrayidx.1
+ %conv.1 = sext i8 %2 to i32
+ %arrayidx2.1 = getelementptr inbounds nuw i8, ptr %y, i64 1
+ %3 = load i8, ptr %arrayidx2.1
+ %conv3.1 = sext i8 %3 to i32
+ %mul.1 = mul nsw i32 %conv3.1, %conv.1
+ %add.1 = add nsw i32 %mul.1, %mul
+ %arrayidx.2 = getelementptr inbounds nuw i8, ptr %x, i64 2
+ %4 = load i8, ptr %arrayidx.2
+ %conv.2 = sext i8 %4 to i32
+ %arrayidx2.2 = getelementptr inbounds nuw i8, ptr %y, i64 2
+ %5 = load i8, ptr %arrayidx2.2
+ %conv3.2 = sext i8 %5 to i32
+ %mul.2 = mul nsw i32 %conv3.2, %conv.2
+ %add.2 = add nsw i32 %mul.2, %add.1
+ %arrayidx.3 = getelementptr inbounds nuw i8, ptr %x, i64 3
+ %6 = load i8, ptr %arrayidx.3
+ %conv.3 = sext i8 %6 to i32
+ %arrayidx2.3 = getelementptr inbounds nuw i8, ptr %y, i64 3
+ %7 = load i8, ptr %arrayidx2.3
+ %conv3.3 = sext i8 %7 to i32
+ %mul.3 = mul nsw i32 %conv3.3, %conv.3
+ %add.3 = add nsw i32 %mul.3, %add.2
+ %arrayidx.4 = getelementptr inbounds nuw i8, ptr %x, i64 4
+ %8 = load i8, ptr %arrayidx.4
+ %conv.4 = sext i8 %8 to i32
+ %arrayidx2.4 = getelementptr inbounds nuw i8, ptr %y, i64 4
+ %9 = load i8, ptr %arrayidx2.4
+ %conv3.4 = sext i8 %9 to i32
+ %mul.4 = mul nsw i32 %conv3.4, %conv.4
+ %add.4 = add nsw i32 %mul.4, %add.3
+ %arrayidx.5 = getelementptr inbounds nuw i8, ptr %x, i64 5
+ %10 = load i8, ptr %arrayidx.5
+ %conv.5 = sext i8 %10 to i32
+ %arrayidx2.5 = getelementptr inbounds nuw i8, ptr %y, i64 5
+ %11 = load i8, ptr %arrayidx2.5
+ %conv3.5 = sext i8 %11 to i32
+ %mul.5 = mul nsw i32 %conv3.5, %conv.5
+ %add.5 = add nsw i32 %mul.5, %add.4
+ %arrayidx.6 = getelementptr inbounds nuw i8, ptr %x, i64 6
+ %12 = load i8, ptr %arrayidx.6
+ %conv.6 = sext i8 %12 to i32
+ %arrayidx2.6 = getelementptr inbounds nuw i8, ptr %y, i64 6
+ %13 = load i8, ptr %arrayidx2.6
+ %conv3.6 = sext i8 %13 to i32
+ %mul.6 = mul nsw i32 %conv3.6, %conv.6
+ %add.6 = add nsw i32 %mul.6, %add.5
+ %arrayidx.7 = getelementptr inbounds nuw i8, ptr %x, i64 7
+ %14 = load i8, ptr %arrayidx.7
+ %conv.7 = sext i8 %14 to i32
+ %arrayidx2.7 = getelementptr inbounds nuw i8, ptr %y, i64 7
+ %15 = load i8, ptr %arrayidx2.7
+ %conv3.7 = sext i8 %15 to i32
+ %mul.7 = mul nsw i32 %conv3.7, %conv.7
+ %add.7 = add nsw i32 %mul.7, %add.6
+ ret i32 %add.7
+}
+
+define i32 @mla_v8i8_i32_no_dotprod(ptr %x, ptr %y) {
+; CHECK-LABEL: @mla_v8i8_i32_no_dotprod(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[X:%.*]], align 1
+; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[TMP0]] to i32
+; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[Y:%.*]], align 1
+; CHECK-NEXT: [[CONV3:%.*]] = sext i8 [[TMP1]] to i32
+; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[CONV3]], [[CONV]]
+; CHECK-NEXT: [[ARRAYIDX_1:%.*]] = getelementptr inbounds nuw i8, ptr [[X]], i64 1
+; CHECK-NEXT: [[TMP2:%.*]] = load i8, ptr [[ARRAYIDX_1]], align 1
+; CHECK-NEXT: [[CONV_1:%.*]] = sext i8 [[TMP2]] to i32
+; CHECK-NEXT: [[ARRAYIDX2_1:%.*]] = getelementptr inbounds nuw i8, ptr [[Y]], i64 1
+; CHECK-NEXT: [[TMP3:%.*]] = load i8, ptr [[ARRAYIDX2_1]], align 1
+; CHECK-NEXT: [[CONV3_1:%.*]] = sext i8 [[TMP3]] to i32
+; CHECK-NEXT: [[MUL_1:%.*]] = mul nsw i32 [[CONV3_1]], [[CONV_1]]
+; CHECK-NEXT: [[ADD_1:%.*]] = add nsw i32 [[MUL_1]], [[MUL]]
+; CHECK-NEXT: [[ARRAYIDX_2:%.*]] = getelementptr inbounds nuw i8, ptr [[X]], i64 2
+; CHECK-NEXT: [[TMP4:%.*]] = load i8, ptr [[ARRAYIDX_2]], align 1
+; CHECK-NEXT: [[CONV_2:%.*]] = sext i8 [[TMP4]] to i32
+; CHECK-NEXT: [[ARRAYIDX2_2:%.*]] = getelementptr inbounds nuw i8, ptr [[Y]], i64 2
+; CHECK-NEXT: [[TMP5:%.*]] = load i8, ptr [[ARRAYIDX2_2]], align 1
+; CHECK-NEXT: [[CONV3_2:%.*]] = sext i8 [[TMP5]] to i32
+; CHECK-NEXT: [[MUL_2:%.*]] = mul nsw i32 [[CONV3_2]], [[CONV_2]]
+; CHECK-NEXT: [[ADD_2:%.*]] = add nsw i32 [[MUL_2]], [[ADD_1]]
+; CHECK-NEXT: [[ARRAYIDX_3:%.*]] = getelementptr inbounds nuw i8, ptr [[X]], i64 3
+; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[ARRAYIDX_3]], align 1
+; CHECK-NEXT: [[CONV_3:%.*]] = sext i8 [[TMP6]] to i32
+; CHECK-NEXT: [[ARRAYIDX2_3:%.*]] = getelementptr inbounds nuw i8, ptr [[Y]], i64 3
+; CHECK-NEXT: [[TMP7:%.*]] = load i8, ptr [[ARRAYIDX2_3]], align 1
+; CHECK-NEXT: [[CONV3_3:%.*]] = sext i8 [[TMP7]] to i32
+; CHECK-NEXT: [[MUL_3:%.*]] = mul nsw i32 [[CONV3_3]], [[CONV_3]]
+; CHECK-NEXT: [[ADD_3:%.*]] = add nsw i32 [[MUL_3]], [[ADD_2]]
+; CHECK-NEXT: [[ARRAYIDX_4:%.*]] = getelementptr inbounds nuw i8, ptr [[X]], i64 4
+; CHECK-NEXT: [[TMP8:%.*]] = load i8, ptr [[ARRAYIDX_4]], align 1
+; CHECK-NEXT: [[CONV_4:%.*]] = sext i8 [[TMP8]] to i32
+; CHECK-NEXT: [[ARRAYIDX2_4:%.*]] = getelementptr inbounds nuw i8, ptr [[Y]], i64 4
+; CHECK-NEXT: [[TMP9:%.*]] = load i8, ptr [[ARRAYIDX2_4]], align 1
+; CHECK-NEXT: [[CONV3_4:%.*]] = sext i8 [[TMP9]] to i32
+; CHECK-NEXT: [[MUL_4:%.*]] = mul nsw i32 [[CONV3_4]], [[CONV_4]]
+; CHECK-NEXT: [[ADD_4:%.*]] = add nsw i32 [[MUL_4]], [[ADD_3]]
+; CHECK-NEXT: [[ARRAYIDX_5:%.*]] = getelementptr inbounds nuw i8, ptr [[X]], i64 5
+; CHECK-NEXT: [[TMP10:%.*]] = load i8, ptr [[ARRAYIDX_5]], align 1
+; CHECK-NEXT: [[CONV_5:%.*]] = sext i8 [[TMP10]] to i32
+; CHECK-NEXT: [[ARRAYIDX2_5:%.*]] = getelementptr inbounds nuw i8, ptr [[Y]], i64 5
+; CHECK-NEXT: [[TMP11:%.*]] = load i8, ptr [[ARRAYIDX2_5]], align 1
+; CHECK-NEXT: [[CONV3_5:%.*]] = sext i8 [[TMP11]] to i32
+; CHECK-NEXT: [[MUL_5:%.*]] = mul nsw i32 [[CONV3_5]], [[CONV_5]]
+; CHECK-NEXT: [[ADD_5:%.*]] = add nsw i32 [[MUL_5]], [[ADD_4]]
+; CHECK-NEXT: [[ARRAYIDX_6:%.*]] = getelementptr inbounds nuw i8, ptr [[X]], i64 6
+; CHECK-NEXT: [[TMP12:%.*]] = load i8, ptr [[ARRAYIDX_6]], align 1
+; CHECK-NEXT: [[CONV_6:%.*]] = sext i8 [[TMP12]] to i32
+; CHECK-NEXT: [[ARRAYIDX2_6:%.*]] = getelementptr inbounds nuw i8, ptr [[Y]], i64 6
+; CHECK-NEXT: [[TMP13:%.*]] = load i8, ptr [[ARRAYIDX2_6]], align 1
+; CHECK-NEXT: [[CONV3_6:%.*]] = sext i8 [[TMP13]] to i32
+; CHECK-NEXT: [[MUL_6:%.*]] = mul nsw i32 [[CONV3_6]], [[CONV_6]]
+; CHECK-NEXT: [[ADD_6:%.*]] = add nsw i32 [[MUL_6]], [[ADD_5]]
+; CHECK-NEXT: [[ARRAYIDX_7:%.*]] = getelementptr inbounds nuw i8, ptr [[X]], i64 7
+; CHECK-NEXT: [[TMP14:%.*]] = load i8, ptr [[ARRAYIDX_7]], align 1
+; CHECK-NEXT: [[CONV_7:%.*]] = sext i8 [[TMP14]] to i32
+; CHECK-NEXT: [[ARRAYIDX2_7:%.*]] = getelementptr inbounds nuw i8, ptr [[Y]], i64 7
+; CHECK-NEXT: [[TMP15:%.*]] = load i8, ptr [[ARRAYIDX2_7]], align 1
+; CHECK-NEXT: [[CONV3_7:%.*]] = sext i8 [[TMP15]] to i32
+; CHECK-NEXT: [[MUL_7:%.*]] = mul nsw i32 [[CONV3_7]], [[CONV_7]]
+; CHECK-NEXT: [[ADD_7:%.*]] = add nsw i32 [[MUL_7]], [[ADD_6]]
+; CHECK-NEXT: ret i32 [[ADD_7]]
+;
+entry:
+ %0 = load i8, ptr %x
+ %conv = sext i8 %0 to i32
+ %1 = load i8, ptr %y
+ %conv3 = sext i8 %1 to i32
+ %mul = mul nsw i32 %conv3, %conv
+ %arrayidx.1 = getelementptr inbounds nuw i8, ptr %x, i64 1
+ %2 = load i8, ptr %arrayidx.1
+ %conv.1 = sext i8 %2 to i32
+ %arrayidx2.1 = getelementptr inbounds nuw i8, ptr %y, i64 1
+ %3 = load i8, ptr %arrayidx2.1
+ %conv3.1 = sext i8 %3 to i32
+ %mul.1 = mul nsw i32 %conv3.1, %conv.1
+ %add.1 = add nsw i32 %mul.1, %mul
+ %arrayidx.2 = getelementptr inbounds nuw i8, ptr %x, i64 2
+ %4 = load i8, ptr %arrayidx.2
+ %conv.2 = sext i8 %4 to i32
+ %arrayidx2.2 = getelementptr inbounds nuw i8, ptr %y, i64 2
+ %5 = load i8, ptr %arrayidx2.2
+ %conv3.2 = sext i8 %5 to i32
+ %mul.2 = mul nsw i32 %conv3.2, %conv.2
+ %add.2 = add nsw i32 %mul.2, %add.1
+ %arrayidx.3 = getelementptr inbounds nuw i8, ptr %x, i64 3
+ %6 = load i8, ptr %arrayidx.3
+ %conv.3 = sext i8 %6 to i32
+ %arrayidx2.3 = getelementptr inbounds nuw i8, ptr %y, i64 3
+ %7 = load i8, ptr %arrayidx2.3
+ %conv3.3 = sext i8 %7 to i32
+ %mul.3 = mul nsw i32 %conv3.3, %conv.3
+ %add.3 = add nsw i32 %mul.3, %add.2
+ %arrayidx.4 = getelementptr inbounds nuw i8, ptr %x, i64 4
+ %8 = load i8, ptr %arrayidx.4
+ %conv.4 = sext i8 %8 to i32
+ %arrayidx2.4 = getelementptr inbounds nuw i8, ptr %y, i64 4
+ %9 = load i8, ptr %arrayidx2.4
+ %conv3.4 = sext i8 %9 to i32
+ %mul.4 = mul nsw i32 %conv3.4, %conv.4
+ %add.4 = add nsw i32 %mul.4, %add.3
+ %arrayidx.5 = getelementptr inbounds nuw i8, ptr %x, i64 5
+ %10 = load i8, ptr %arrayidx.5
+ %conv.5 = sext i8 %10 to i32
+ %arrayidx2.5 = getelementptr inbounds nuw i8, ptr %y, i64 5
+ %11 = load i8, ptr %arrayidx2.5
+ %conv3.5 = sext i8 %11 to i32
+ %mul.5 = mul nsw i32 %conv3.5, %conv.5
+ %add.5 = add nsw i32 %mul.5, %add.4
+ %arrayidx.6 = getelementptr inbounds nuw i8, ptr %x, i64 6
+ %12 = load i8, ptr %arrayidx.6
+ %conv.6 = sext i8 %12 to i32
+ %arrayidx2.6 = getelementptr inbounds nuw i8, ptr %y, i64 6
+ %13 = load i8, ptr %arrayidx2.6
+ %conv3.6 = sext i8 %13 to i32
+ %mul.6 = mul nsw i32 %conv3.6, %conv.6
+ %add.6 = add nsw i32 %mul.6, %add.5
+ %arrayidx.7 = getelementptr inbounds nuw i8, ptr %x, i64 7
+ %14 = load i8, ptr %arrayidx.7
+ %conv.7 = sext i8 %14 to i32
+ %arrayidx2.7 = getelementptr inbounds nuw i8, ptr %y, i64 7
+ %15 = load i8, ptr %arrayidx2.7
+ %conv3.7 = sext i8 %15 to i32
+ %mul.7 = mul nsw i32 %conv3.7, %conv.7
+ %add.7 = add nsw i32 %mul.7, %add.6
+ ret i32 %add.7
+}
>From b6ef1cdae75158cd8a37eb5b061c975b95645ebf Mon Sep 17 00:00:00 2001
From: Madhur Amilkanthwar <madhura at nvidia.com>
Date: Fri, 18 Sep 2026 04:00:23 -0700
Subject: [PATCH 2/2] fixup! [SLP][NFC] Add precommit test for dot-product
reduction costing
---
.../AArch64/reduce-add-dotprod.ll | 147 ++----------------
1 file changed, 9 insertions(+), 138 deletions(-)
diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/reduce-add-dotprod.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/reduce-add-dotprod.ll
index 36d2a0f797280..4339610179600 100644
--- a/llvm/test/Transforms/SLPVectorizer/AArch64/reduce-add-dotprod.ll
+++ b/llvm/test/Transforms/SLPVectorizer/AArch64/reduce-add-dotprod.ll
@@ -1,148 +1,16 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -passes=slp-vectorizer -slp-threshold=28 -S -mtriple=aarch64 < %s | FileCheck %s
+; RUN: opt -passes=slp-vectorizer -slp-threshold=28 -S -mtriple=aarch64 -mattr=+dotprod < %s | FileCheck %s --check-prefixes=CHECK,DOTPROD
+; RUN: opt -passes=slp-vectorizer -slp-threshold=28 -S -mtriple=aarch64 < %s | FileCheck %s --check-prefixes=CHECK,NODOTPROD
; The reduce.add(mul(ext, ext)) idiom lowers to a single dot-product
; reduction (UDOT/SDOT) when the target supports it. The threshold is set
; between the plain reduction cost and the fused dot-product cost so the
-; reduction is profitable only when the dot-product cost applies: the
-; +dotprod function vectorizes, the plain function stays scalar.
+; reduction is profitable only when the dot-product cost applies: with
+; +dotprod the reduction vectorizes, without it the code stays scalar.
-target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32"
-target triple = "aarch64"
-
-define i32 @mla_v8i8_i32_dotprod(ptr %x, ptr %y) "target-features"="+dotprod" {
-; CHECK-LABEL: @mla_v8i8_i32_dotprod(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[X:%.*]], align 1
-; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[TMP0]] to i32
-; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[Y:%.*]], align 1
-; CHECK-NEXT: [[CONV3:%.*]] = sext i8 [[TMP1]] to i32
-; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[CONV3]], [[CONV]]
-; CHECK-NEXT: [[ARRAYIDX_1:%.*]] = getelementptr inbounds nuw i8, ptr [[X]], i64 1
-; CHECK-NEXT: [[TMP2:%.*]] = load i8, ptr [[ARRAYIDX_1]], align 1
-; CHECK-NEXT: [[CONV_1:%.*]] = sext i8 [[TMP2]] to i32
-; CHECK-NEXT: [[ARRAYIDX2_1:%.*]] = getelementptr inbounds nuw i8, ptr [[Y]], i64 1
-; CHECK-NEXT: [[TMP3:%.*]] = load i8, ptr [[ARRAYIDX2_1]], align 1
-; CHECK-NEXT: [[CONV3_1:%.*]] = sext i8 [[TMP3]] to i32
-; CHECK-NEXT: [[MUL_1:%.*]] = mul nsw i32 [[CONV3_1]], [[CONV_1]]
-; CHECK-NEXT: [[ADD_1:%.*]] = add nsw i32 [[MUL_1]], [[MUL]]
-; CHECK-NEXT: [[ARRAYIDX_2:%.*]] = getelementptr inbounds nuw i8, ptr [[X]], i64 2
-; CHECK-NEXT: [[TMP4:%.*]] = load i8, ptr [[ARRAYIDX_2]], align 1
-; CHECK-NEXT: [[CONV_2:%.*]] = sext i8 [[TMP4]] to i32
-; CHECK-NEXT: [[ARRAYIDX2_2:%.*]] = getelementptr inbounds nuw i8, ptr [[Y]], i64 2
-; CHECK-NEXT: [[TMP16:%.*]] = load i8, ptr [[ARRAYIDX2_2]], align 1
-; CHECK-NEXT: [[CONV3_2:%.*]] = sext i8 [[TMP16]] to i32
-; CHECK-NEXT: [[MUL_2:%.*]] = mul nsw i32 [[CONV3_2]], [[CONV_2]]
-; CHECK-NEXT: [[ADD_2:%.*]] = add nsw i32 [[MUL_2]], [[ADD_1]]
-; CHECK-NEXT: [[ARRAYIDX_3:%.*]] = getelementptr inbounds nuw i8, ptr [[X]], i64 3
-; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[ARRAYIDX_3]], align 1
-; CHECK-NEXT: [[CONV_3:%.*]] = sext i8 [[TMP6]] to i32
-; CHECK-NEXT: [[ARRAYIDX2_3:%.*]] = getelementptr inbounds nuw i8, ptr [[Y]], i64 3
-; CHECK-NEXT: [[TMP7:%.*]] = load i8, ptr [[ARRAYIDX2_3]], align 1
-; CHECK-NEXT: [[CONV3_3:%.*]] = sext i8 [[TMP7]] to i32
-; CHECK-NEXT: [[MUL_3:%.*]] = mul nsw i32 [[CONV3_3]], [[CONV_3]]
-; CHECK-NEXT: [[ADD_3:%.*]] = add nsw i32 [[MUL_3]], [[ADD_2]]
-; CHECK-NEXT: [[ARRAYIDX_4:%.*]] = getelementptr inbounds nuw i8, ptr [[X]], i64 4
-; CHECK-NEXT: [[TMP8:%.*]] = load i8, ptr [[ARRAYIDX_4]], align 1
-; CHECK-NEXT: [[CONV_4:%.*]] = sext i8 [[TMP8]] to i32
-; CHECK-NEXT: [[ARRAYIDX2_4:%.*]] = getelementptr inbounds nuw i8, ptr [[Y]], i64 4
-; CHECK-NEXT: [[TMP9:%.*]] = load i8, ptr [[ARRAYIDX2_4]], align 1
-; CHECK-NEXT: [[CONV3_4:%.*]] = sext i8 [[TMP9]] to i32
-; CHECK-NEXT: [[MUL_4:%.*]] = mul nsw i32 [[CONV3_4]], [[CONV_4]]
-; CHECK-NEXT: [[ADD_4:%.*]] = add nsw i32 [[MUL_4]], [[ADD_3]]
-; CHECK-NEXT: [[ARRAYIDX_5:%.*]] = getelementptr inbounds nuw i8, ptr [[X]], i64 5
-; CHECK-NEXT: [[TMP10:%.*]] = load i8, ptr [[ARRAYIDX_5]], align 1
-; CHECK-NEXT: [[CONV_5:%.*]] = sext i8 [[TMP10]] to i32
-; CHECK-NEXT: [[ARRAYIDX2_5:%.*]] = getelementptr inbounds nuw i8, ptr [[Y]], i64 5
-; CHECK-NEXT: [[TMP11:%.*]] = load i8, ptr [[ARRAYIDX2_5]], align 1
-; CHECK-NEXT: [[CONV3_5:%.*]] = sext i8 [[TMP11]] to i32
-; CHECK-NEXT: [[MUL_5:%.*]] = mul nsw i32 [[CONV3_5]], [[CONV_5]]
-; CHECK-NEXT: [[ADD_5:%.*]] = add nsw i32 [[MUL_5]], [[ADD_4]]
-; CHECK-NEXT: [[ARRAYIDX_6:%.*]] = getelementptr inbounds nuw i8, ptr [[X]], i64 6
-; CHECK-NEXT: [[TMP12:%.*]] = load i8, ptr [[ARRAYIDX_6]], align 1
-; CHECK-NEXT: [[CONV_6:%.*]] = sext i8 [[TMP12]] to i32
-; CHECK-NEXT: [[ARRAYIDX2_6:%.*]] = getelementptr inbounds nuw i8, ptr [[Y]], i64 6
-; CHECK-NEXT: [[TMP13:%.*]] = load i8, ptr [[ARRAYIDX2_6]], align 1
-; CHECK-NEXT: [[CONV3_6:%.*]] = sext i8 [[TMP13]] to i32
-; CHECK-NEXT: [[MUL_6:%.*]] = mul nsw i32 [[CONV3_6]], [[CONV_6]]
-; CHECK-NEXT: [[ADD_6:%.*]] = add nsw i32 [[MUL_6]], [[ADD_5]]
-; CHECK-NEXT: [[ARRAYIDX_7:%.*]] = getelementptr inbounds nuw i8, ptr [[X]], i64 7
-; CHECK-NEXT: [[TMP14:%.*]] = load i8, ptr [[ARRAYIDX_7]], align 1
-; CHECK-NEXT: [[CONV_7:%.*]] = sext i8 [[TMP14]] to i32
-; CHECK-NEXT: [[ARRAYIDX2_7:%.*]] = getelementptr inbounds nuw i8, ptr [[Y]], i64 7
-; CHECK-NEXT: [[TMP15:%.*]] = load i8, ptr [[ARRAYIDX2_7]], align 1
-; CHECK-NEXT: [[CONV3_7:%.*]] = sext i8 [[TMP15]] to i32
-; CHECK-NEXT: [[MUL_7:%.*]] = mul nsw i32 [[CONV3_7]], [[CONV_7]]
-; CHECK-NEXT: [[TMP5:%.*]] = add nsw i32 [[MUL_7]], [[ADD_6]]
-; CHECK-NEXT: ret i32 [[TMP5]]
+define i32 @mla_v8i8_i32(ptr %x, ptr %y) {
;
-entry:
- %0 = load i8, ptr %x
- %conv = sext i8 %0 to i32
- %1 = load i8, ptr %y
- %conv3 = sext i8 %1 to i32
- %mul = mul nsw i32 %conv3, %conv
- %arrayidx.1 = getelementptr inbounds nuw i8, ptr %x, i64 1
- %2 = load i8, ptr %arrayidx.1
- %conv.1 = sext i8 %2 to i32
- %arrayidx2.1 = getelementptr inbounds nuw i8, ptr %y, i64 1
- %3 = load i8, ptr %arrayidx2.1
- %conv3.1 = sext i8 %3 to i32
- %mul.1 = mul nsw i32 %conv3.1, %conv.1
- %add.1 = add nsw i32 %mul.1, %mul
- %arrayidx.2 = getelementptr inbounds nuw i8, ptr %x, i64 2
- %4 = load i8, ptr %arrayidx.2
- %conv.2 = sext i8 %4 to i32
- %arrayidx2.2 = getelementptr inbounds nuw i8, ptr %y, i64 2
- %5 = load i8, ptr %arrayidx2.2
- %conv3.2 = sext i8 %5 to i32
- %mul.2 = mul nsw i32 %conv3.2, %conv.2
- %add.2 = add nsw i32 %mul.2, %add.1
- %arrayidx.3 = getelementptr inbounds nuw i8, ptr %x, i64 3
- %6 = load i8, ptr %arrayidx.3
- %conv.3 = sext i8 %6 to i32
- %arrayidx2.3 = getelementptr inbounds nuw i8, ptr %y, i64 3
- %7 = load i8, ptr %arrayidx2.3
- %conv3.3 = sext i8 %7 to i32
- %mul.3 = mul nsw i32 %conv3.3, %conv.3
- %add.3 = add nsw i32 %mul.3, %add.2
- %arrayidx.4 = getelementptr inbounds nuw i8, ptr %x, i64 4
- %8 = load i8, ptr %arrayidx.4
- %conv.4 = sext i8 %8 to i32
- %arrayidx2.4 = getelementptr inbounds nuw i8, ptr %y, i64 4
- %9 = load i8, ptr %arrayidx2.4
- %conv3.4 = sext i8 %9 to i32
- %mul.4 = mul nsw i32 %conv3.4, %conv.4
- %add.4 = add nsw i32 %mul.4, %add.3
- %arrayidx.5 = getelementptr inbounds nuw i8, ptr %x, i64 5
- %10 = load i8, ptr %arrayidx.5
- %conv.5 = sext i8 %10 to i32
- %arrayidx2.5 = getelementptr inbounds nuw i8, ptr %y, i64 5
- %11 = load i8, ptr %arrayidx2.5
- %conv3.5 = sext i8 %11 to i32
- %mul.5 = mul nsw i32 %conv3.5, %conv.5
- %add.5 = add nsw i32 %mul.5, %add.4
- %arrayidx.6 = getelementptr inbounds nuw i8, ptr %x, i64 6
- %12 = load i8, ptr %arrayidx.6
- %conv.6 = sext i8 %12 to i32
- %arrayidx2.6 = getelementptr inbounds nuw i8, ptr %y, i64 6
- %13 = load i8, ptr %arrayidx2.6
- %conv3.6 = sext i8 %13 to i32
- %mul.6 = mul nsw i32 %conv3.6, %conv.6
- %add.6 = add nsw i32 %mul.6, %add.5
- %arrayidx.7 = getelementptr inbounds nuw i8, ptr %x, i64 7
- %14 = load i8, ptr %arrayidx.7
- %conv.7 = sext i8 %14 to i32
- %arrayidx2.7 = getelementptr inbounds nuw i8, ptr %y, i64 7
- %15 = load i8, ptr %arrayidx2.7
- %conv3.7 = sext i8 %15 to i32
- %mul.7 = mul nsw i32 %conv3.7, %conv.7
- %add.7 = add nsw i32 %mul.7, %add.6
- ret i32 %add.7
-}
-
-define i32 @mla_v8i8_i32_no_dotprod(ptr %x, ptr %y) {
-; CHECK-LABEL: @mla_v8i8_i32_no_dotprod(
+; CHECK-LABEL: @mla_v8i8_i32(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[X:%.*]], align 1
; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[TMP0]] to i32
@@ -271,3 +139,6 @@ entry:
%add.7 = add nsw i32 %mul.7, %add.6
ret i32 %add.7
}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; DOTPROD: {{.*}}
+; NODOTPROD: {{.*}}
More information about the llvm-commits
mailing list