[llvm-branch-commits] [llvm] [TTI] Add cost for @llvm.mask.beforefirst (PR #212174)
Luke Lau via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Oct 23 06:48:40 PDT 2026
https://github.com/lukel97 updated https://github.com/llvm/llvm-project/pull/212174
>From 66b3fcf9364c6cb1ccf7452205819a7f0a87f027 Mon Sep 17 00:00:00 2001
From: Luke Lau <luke at igalia.com>
Date: Mon, 20 Jul 2026 22:31:01 +0800
Subject: [PATCH 1/3] Precommit tests
---
.../CostModel/AArch64/mask-beforefirst.ll | 44 +++++++++++++++++++
.../CostModel/RISCV/mask-beforefirst.ll | 42 ++++++++++++++++++
2 files changed, 86 insertions(+)
create mode 100644 llvm/test/Analysis/CostModel/AArch64/mask-beforefirst.ll
create mode 100644 llvm/test/Analysis/CostModel/RISCV/mask-beforefirst.ll
diff --git a/llvm/test/Analysis/CostModel/AArch64/mask-beforefirst.ll b/llvm/test/Analysis/CostModel/AArch64/mask-beforefirst.ll
new file mode 100644
index 00000000000000..33b71fea896588
--- /dev/null
+++ b/llvm/test/Analysis/CostModel/AArch64/mask-beforefirst.ll
@@ -0,0 +1,44 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -passes="print<cost-model>" 2>&1 -disable-output -mtriple=aarch64 -mattr=+sve | FileCheck %s --check-prefix=SVE
+; RUN: opt < %s -passes="print<cost-model>" 2>&1 -disable-output -mtriple=aarch64 | FileCheck %s --check-prefix=NEON
+
+define void @mask_beforefirst() {
+; SVE-LABEL: 'mask_beforefirst'
+; SVE-NEXT: Cost Model: Invalid cost for instruction: %1 = call <vscale x 2 x i1> @llvm.mask.beforefirst.nxv2i1(<vscale x 2 x i1> poison)
+; SVE-NEXT: Cost Model: Invalid cost for instruction: %2 = call <vscale x 4 x i1> @llvm.mask.beforefirst.nxv4i1(<vscale x 4 x i1> poison)
+; SVE-NEXT: Cost Model: Invalid cost for instruction: %3 = call <vscale x 8 x i1> @llvm.mask.beforefirst.nxv8i1(<vscale x 8 x i1> poison)
+; SVE-NEXT: Cost Model: Invalid cost for instruction: %4 = call <vscale x 16 x i1> @llvm.mask.beforefirst.nxv16i1(<vscale x 16 x i1> poison)
+; SVE-NEXT: Cost Model: Invalid cost for instruction: %5 = call <vscale x 32 x i1> @llvm.mask.beforefirst.nxv32i1(<vscale x 32 x i1> poison)
+; SVE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %6 = call <2 x i1> @llvm.mask.beforefirst.v2i1(<2 x i1> poison)
+; SVE-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %7 = call <4 x i1> @llvm.mask.beforefirst.v4i1(<4 x i1> poison)
+; SVE-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %8 = call <8 x i1> @llvm.mask.beforefirst.v8i1(<8 x i1> poison)
+; SVE-NEXT: Cost Model: Found an estimated cost of 48 for instruction: %9 = call <16 x i1> @llvm.mask.beforefirst.v16i1(<16 x i1> poison)
+; SVE-NEXT: Cost Model: Found an estimated cost of 96 for instruction: %10 = call <32 x i1> @llvm.mask.beforefirst.v32i1(<32 x i1> poison)
+; SVE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void
+;
+; NEON-LABEL: 'mask_beforefirst'
+; NEON-NEXT: Cost Model: Invalid cost for instruction: %1 = call <vscale x 2 x i1> @llvm.mask.beforefirst.nxv2i1(<vscale x 2 x i1> poison)
+; NEON-NEXT: Cost Model: Invalid cost for instruction: %2 = call <vscale x 4 x i1> @llvm.mask.beforefirst.nxv4i1(<vscale x 4 x i1> poison)
+; NEON-NEXT: Cost Model: Invalid cost for instruction: %3 = call <vscale x 8 x i1> @llvm.mask.beforefirst.nxv8i1(<vscale x 8 x i1> poison)
+; NEON-NEXT: Cost Model: Invalid cost for instruction: %4 = call <vscale x 16 x i1> @llvm.mask.beforefirst.nxv16i1(<vscale x 16 x i1> poison)
+; NEON-NEXT: Cost Model: Invalid cost for instruction: %5 = call <vscale x 32 x i1> @llvm.mask.beforefirst.nxv32i1(<vscale x 32 x i1> poison)
+; NEON-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %6 = call <2 x i1> @llvm.mask.beforefirst.v2i1(<2 x i1> poison)
+; NEON-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %7 = call <4 x i1> @llvm.mask.beforefirst.v4i1(<4 x i1> poison)
+; NEON-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %8 = call <8 x i1> @llvm.mask.beforefirst.v8i1(<8 x i1> poison)
+; NEON-NEXT: Cost Model: Found an estimated cost of 48 for instruction: %9 = call <16 x i1> @llvm.mask.beforefirst.v16i1(<16 x i1> poison)
+; NEON-NEXT: Cost Model: Found an estimated cost of 96 for instruction: %10 = call <32 x i1> @llvm.mask.beforefirst.v32i1(<32 x i1> poison)
+; NEON-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void
+;
+ call <vscale x 2 x i1> @llvm.mask.beforefirst(<vscale x 2 x i1> poison)
+ call <vscale x 4 x i1> @llvm.mask.beforefirst(<vscale x 4 x i1> poison)
+ call <vscale x 8 x i1> @llvm.mask.beforefirst(<vscale x 8 x i1> poison)
+ call <vscale x 16 x i1> @llvm.mask.beforefirst(<vscale x 16 x i1> poison)
+ call <vscale x 32 x i1> @llvm.mask.beforefirst(<vscale x 32 x i1> poison)
+ call <2 x i1> @llvm.mask.beforefirst(<2 x i1> poison)
+ call <4 x i1> @llvm.mask.beforefirst(<4 x i1> poison)
+ call <8 x i1> @llvm.mask.beforefirst(<8 x i1> poison)
+ call <16 x i1> @llvm.mask.beforefirst(<16 x i1> poison)
+ call <32 x i1> @llvm.mask.beforefirst(<32 x i1> poison)
+
+ ret void
+}
diff --git a/llvm/test/Analysis/CostModel/RISCV/mask-beforefirst.ll b/llvm/test/Analysis/CostModel/RISCV/mask-beforefirst.ll
new file mode 100644
index 00000000000000..5adce6095b16ac
--- /dev/null
+++ b/llvm/test/Analysis/CostModel/RISCV/mask-beforefirst.ll
@@ -0,0 +1,42 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -passes='print<cost-model>' 2>&1 -disable-output -mtriple=riscv64 -mattr=+v | FileCheck %s
+
+define void @mask_beforefirst() {
+; CHECK-LABEL: 'mask_beforefirst'
+; CHECK-NEXT: Cost Model: Invalid cost for instruction: %1 = call <vscale x 1 x i1> @llvm.mask.beforefirst.nxv1i1(<vscale x 1 x i1> poison)
+; CHECK-NEXT: Cost Model: Invalid cost for instruction: %2 = call <vscale x 2 x i1> @llvm.mask.beforefirst.nxv2i1(<vscale x 2 x i1> poison)
+; CHECK-NEXT: Cost Model: Invalid cost for instruction: %3 = call <vscale x 4 x i1> @llvm.mask.beforefirst.nxv4i1(<vscale x 4 x i1> poison)
+; CHECK-NEXT: Cost Model: Invalid cost for instruction: %4 = call <vscale x 8 x i1> @llvm.mask.beforefirst.nxv8i1(<vscale x 8 x i1> poison)
+; CHECK-NEXT: Cost Model: Invalid cost for instruction: %5 = call <vscale x 16 x i1> @llvm.mask.beforefirst.nxv16i1(<vscale x 16 x i1> poison)
+; CHECK-NEXT: Cost Model: Invalid cost for instruction: %6 = call <vscale x 32 x i1> @llvm.mask.beforefirst.nxv32i1(<vscale x 32 x i1> poison)
+; CHECK-NEXT: Cost Model: Invalid cost for instruction: %7 = call <vscale x 64 x i1> @llvm.mask.beforefirst.nxv64i1(<vscale x 64 x i1> poison)
+; CHECK-NEXT: Cost Model: Invalid cost for instruction: %8 = call <vscale x 128 x i1> @llvm.mask.beforefirst.nxv128i1(<vscale x 128 x i1> poison)
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %9 = call <1 x i1> @llvm.mask.beforefirst.v1i1(<1 x i1> poison)
+; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %10 = call <2 x i1> @llvm.mask.beforefirst.v2i1(<2 x i1> poison)
+; CHECK-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %11 = call <4 x i1> @llvm.mask.beforefirst.v4i1(<4 x i1> poison)
+; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %12 = call <8 x i1> @llvm.mask.beforefirst.v8i1(<8 x i1> poison)
+; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %13 = call <16 x i1> @llvm.mask.beforefirst.v16i1(<16 x i1> poison)
+; CHECK-NEXT: Cost Model: Found an estimated cost of 99 for instruction: %14 = call <32 x i1> @llvm.mask.beforefirst.v32i1(<32 x i1> poison)
+; CHECK-NEXT: Cost Model: Found an estimated cost of 199 for instruction: %15 = call <64 x i1> @llvm.mask.beforefirst.v64i1(<64 x i1> poison)
+; CHECK-NEXT: Cost Model: Found an estimated cost of 399 for instruction: %16 = call <128 x i1> @llvm.mask.beforefirst.v128i1(<128 x i1> poison)
+; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void
+;
+ call <vscale x 1 x i1> @llvm.mask.beforefirst(<vscale x 1 x i1> poison)
+ call <vscale x 2 x i1> @llvm.mask.beforefirst(<vscale x 2 x i1> poison)
+ call <vscale x 4 x i1> @llvm.mask.beforefirst(<vscale x 4 x i1> poison)
+ call <vscale x 8 x i1> @llvm.mask.beforefirst(<vscale x 8 x i1> poison)
+ call <vscale x 16 x i1> @llvm.mask.beforefirst(<vscale x 16 x i1> poison)
+ call <vscale x 32 x i1> @llvm.mask.beforefirst(<vscale x 32 x i1> poison)
+ call <vscale x 64 x i1> @llvm.mask.beforefirst(<vscale x 64 x i1> poison)
+ call <vscale x 128 x i1> @llvm.mask.beforefirst(<vscale x 128 x i1> poison)
+ call <1 x i1> @llvm.mask.beforefirst(<1 x i1> poison)
+ call <2 x i1> @llvm.mask.beforefirst(<2 x i1> poison)
+ call <4 x i1> @llvm.mask.beforefirst(<4 x i1> poison)
+ call <8 x i1> @llvm.mask.beforefirst(<8 x i1> poison)
+ call <16 x i1> @llvm.mask.beforefirst(<16 x i1> poison)
+ call <32 x i1> @llvm.mask.beforefirst(<32 x i1> poison)
+ call <64 x i1> @llvm.mask.beforefirst(<64 x i1> poison)
+ call <128 x i1> @llvm.mask.beforefirst(<128 x i1> poison)
+
+ ret void
+}
>From c78bd3a92eecec816e90cbd91017a3564b8d34a9 Mon Sep 17 00:00:00 2001
From: Luke Lau <luke at igalia.com>
Date: Mon, 20 Jul 2026 23:45:57 +0800
Subject: [PATCH 2/3] [TTI] Add cost for llvm.mask.beforefirst
---
llvm/include/llvm/CodeGen/BasicTTIImpl.h | 23 +++++++++++++
.../CostModel/AArch64/mask-beforefirst.ll | 30 ++++++++---------
.../CostModel/RISCV/mask-beforefirst.ll | 32 +++++++++----------
3 files changed, 54 insertions(+), 31 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/BasicTTIImpl.h b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
index 0cebf7ae5a6b26..54f61e0d55c4da 100644
--- a/llvm/include/llvm/CodeGen/BasicTTIImpl.h
+++ b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
@@ -2187,6 +2187,7 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
return Cost;
}
case Intrinsic::get_active_lane_mask:
+ case Intrinsic::mask_beforefirst:
case Intrinsic::experimental_vector_match:
case Intrinsic::experimental_vector_histogram_add:
case Intrinsic::experimental_vector_histogram_uadd_sat:
@@ -2683,6 +2684,28 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
CmpInst::ICMP_ULT, CostKind);
return Cost;
}
+ case Intrinsic::mask_beforefirst: {
+ ISD = ISD::MASK_BEFOREFIRST;
+ std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(RetTy);
+ if (!getTLI()->isOperationExpand(ISD, LT.second))
+ break;
+
+ // Expansion via (get_active_lane_mask 0, (cttz.elts mask))
+ RetTy = VectorType::get(RetTy->getScalarType(),
+ LT.second.getVectorElementCount());
+ Type *IdxTy =
+ IntegerType::get(RetTy->getContext(),
+ getTLI()->getVectorIdxTy(DL).getFixedSizeInBits());
+ IntrinsicCostAttributes CttzEltsAttrs(Intrinsic::experimental_cttz_elts,
+ IdxTy, RetTy, FMF);
+ InstructionCost Cost =
+ thisT()->getIntrinsicInstrCost(CttzEltsAttrs, CostKind);
+
+ IntrinsicCostAttributes ActiveLaneMaskAttrs(
+ Intrinsic::get_active_lane_mask, RetTy, {IdxTy, IdxTy}, FMF);
+ Cost += thisT()->getIntrinsicInstrCost(ActiveLaneMaskAttrs, CostKind);
+ return Cost * LT.first;
+ }
case Intrinsic::experimental_memset_pattern:
// This cost is set to match the cost of the memset_pattern16 libcall.
// It should likely be re-evaluated after migration to this intrinsic
diff --git a/llvm/test/Analysis/CostModel/AArch64/mask-beforefirst.ll b/llvm/test/Analysis/CostModel/AArch64/mask-beforefirst.ll
index 33b71fea896588..48a6200141be03 100644
--- a/llvm/test/Analysis/CostModel/AArch64/mask-beforefirst.ll
+++ b/llvm/test/Analysis/CostModel/AArch64/mask-beforefirst.ll
@@ -4,16 +4,16 @@
define void @mask_beforefirst() {
; SVE-LABEL: 'mask_beforefirst'
-; SVE-NEXT: Cost Model: Invalid cost for instruction: %1 = call <vscale x 2 x i1> @llvm.mask.beforefirst.nxv2i1(<vscale x 2 x i1> poison)
-; SVE-NEXT: Cost Model: Invalid cost for instruction: %2 = call <vscale x 4 x i1> @llvm.mask.beforefirst.nxv4i1(<vscale x 4 x i1> poison)
-; SVE-NEXT: Cost Model: Invalid cost for instruction: %3 = call <vscale x 8 x i1> @llvm.mask.beforefirst.nxv8i1(<vscale x 8 x i1> poison)
-; SVE-NEXT: Cost Model: Invalid cost for instruction: %4 = call <vscale x 16 x i1> @llvm.mask.beforefirst.nxv16i1(<vscale x 16 x i1> poison)
-; SVE-NEXT: Cost Model: Invalid cost for instruction: %5 = call <vscale x 32 x i1> @llvm.mask.beforefirst.nxv32i1(<vscale x 32 x i1> poison)
-; SVE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %6 = call <2 x i1> @llvm.mask.beforefirst.v2i1(<2 x i1> poison)
-; SVE-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %7 = call <4 x i1> @llvm.mask.beforefirst.v4i1(<4 x i1> poison)
-; SVE-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %8 = call <8 x i1> @llvm.mask.beforefirst.v8i1(<8 x i1> poison)
-; SVE-NEXT: Cost Model: Found an estimated cost of 48 for instruction: %9 = call <16 x i1> @llvm.mask.beforefirst.v16i1(<16 x i1> poison)
-; SVE-NEXT: Cost Model: Found an estimated cost of 96 for instruction: %10 = call <32 x i1> @llvm.mask.beforefirst.v32i1(<32 x i1> poison)
+; SVE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %1 = call <vscale x 2 x i1> @llvm.mask.beforefirst.nxv2i1(<vscale x 2 x i1> poison)
+; SVE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %2 = call <vscale x 4 x i1> @llvm.mask.beforefirst.nxv4i1(<vscale x 4 x i1> poison)
+; SVE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %3 = call <vscale x 8 x i1> @llvm.mask.beforefirst.nxv8i1(<vscale x 8 x i1> poison)
+; SVE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = call <vscale x 16 x i1> @llvm.mask.beforefirst.nxv16i1(<vscale x 16 x i1> poison)
+; SVE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %5 = call <vscale x 32 x i1> @llvm.mask.beforefirst.nxv32i1(<vscale x 32 x i1> poison)
+; SVE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %6 = call <2 x i1> @llvm.mask.beforefirst.v2i1(<2 x i1> poison)
+; SVE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %7 = call <4 x i1> @llvm.mask.beforefirst.v4i1(<4 x i1> poison)
+; SVE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %8 = call <8 x i1> @llvm.mask.beforefirst.v8i1(<8 x i1> poison)
+; SVE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %9 = call <16 x i1> @llvm.mask.beforefirst.v16i1(<16 x i1> poison)
+; SVE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %10 = call <32 x i1> @llvm.mask.beforefirst.v32i1(<32 x i1> poison)
; SVE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void
;
; NEON-LABEL: 'mask_beforefirst'
@@ -22,11 +22,11 @@ define void @mask_beforefirst() {
; NEON-NEXT: Cost Model: Invalid cost for instruction: %3 = call <vscale x 8 x i1> @llvm.mask.beforefirst.nxv8i1(<vscale x 8 x i1> poison)
; NEON-NEXT: Cost Model: Invalid cost for instruction: %4 = call <vscale x 16 x i1> @llvm.mask.beforefirst.nxv16i1(<vscale x 16 x i1> poison)
; NEON-NEXT: Cost Model: Invalid cost for instruction: %5 = call <vscale x 32 x i1> @llvm.mask.beforefirst.nxv32i1(<vscale x 32 x i1> poison)
-; NEON-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %6 = call <2 x i1> @llvm.mask.beforefirst.v2i1(<2 x i1> poison)
-; NEON-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %7 = call <4 x i1> @llvm.mask.beforefirst.v4i1(<4 x i1> poison)
-; NEON-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %8 = call <8 x i1> @llvm.mask.beforefirst.v8i1(<8 x i1> poison)
-; NEON-NEXT: Cost Model: Found an estimated cost of 48 for instruction: %9 = call <16 x i1> @llvm.mask.beforefirst.v16i1(<16 x i1> poison)
-; NEON-NEXT: Cost Model: Found an estimated cost of 96 for instruction: %10 = call <32 x i1> @llvm.mask.beforefirst.v32i1(<32 x i1> poison)
+; NEON-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %6 = call <2 x i1> @llvm.mask.beforefirst.v2i1(<2 x i1> poison)
+; NEON-NEXT: Cost Model: Found an estimated cost of 20 for instruction: %7 = call <4 x i1> @llvm.mask.beforefirst.v4i1(<4 x i1> poison)
+; NEON-NEXT: Cost Model: Found an estimated cost of 40 for instruction: %8 = call <8 x i1> @llvm.mask.beforefirst.v8i1(<8 x i1> poison)
+; NEON-NEXT: Cost Model: Found an estimated cost of 80 for instruction: %9 = call <16 x i1> @llvm.mask.beforefirst.v16i1(<16 x i1> poison)
+; NEON-NEXT: Cost Model: Found an estimated cost of 160 for instruction: %10 = call <32 x i1> @llvm.mask.beforefirst.v32i1(<32 x i1> poison)
; NEON-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void
;
call <vscale x 2 x i1> @llvm.mask.beforefirst(<vscale x 2 x i1> poison)
diff --git a/llvm/test/Analysis/CostModel/RISCV/mask-beforefirst.ll b/llvm/test/Analysis/CostModel/RISCV/mask-beforefirst.ll
index 5adce6095b16ac..4c71dd6bf5a513 100644
--- a/llvm/test/Analysis/CostModel/RISCV/mask-beforefirst.ll
+++ b/llvm/test/Analysis/CostModel/RISCV/mask-beforefirst.ll
@@ -3,22 +3,22 @@
define void @mask_beforefirst() {
; CHECK-LABEL: 'mask_beforefirst'
-; CHECK-NEXT: Cost Model: Invalid cost for instruction: %1 = call <vscale x 1 x i1> @llvm.mask.beforefirst.nxv1i1(<vscale x 1 x i1> poison)
-; CHECK-NEXT: Cost Model: Invalid cost for instruction: %2 = call <vscale x 2 x i1> @llvm.mask.beforefirst.nxv2i1(<vscale x 2 x i1> poison)
-; CHECK-NEXT: Cost Model: Invalid cost for instruction: %3 = call <vscale x 4 x i1> @llvm.mask.beforefirst.nxv4i1(<vscale x 4 x i1> poison)
-; CHECK-NEXT: Cost Model: Invalid cost for instruction: %4 = call <vscale x 8 x i1> @llvm.mask.beforefirst.nxv8i1(<vscale x 8 x i1> poison)
-; CHECK-NEXT: Cost Model: Invalid cost for instruction: %5 = call <vscale x 16 x i1> @llvm.mask.beforefirst.nxv16i1(<vscale x 16 x i1> poison)
-; CHECK-NEXT: Cost Model: Invalid cost for instruction: %6 = call <vscale x 32 x i1> @llvm.mask.beforefirst.nxv32i1(<vscale x 32 x i1> poison)
-; CHECK-NEXT: Cost Model: Invalid cost for instruction: %7 = call <vscale x 64 x i1> @llvm.mask.beforefirst.nxv64i1(<vscale x 64 x i1> poison)
-; CHECK-NEXT: Cost Model: Invalid cost for instruction: %8 = call <vscale x 128 x i1> @llvm.mask.beforefirst.nxv128i1(<vscale x 128 x i1> poison)
-; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %9 = call <1 x i1> @llvm.mask.beforefirst.v1i1(<1 x i1> poison)
-; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %10 = call <2 x i1> @llvm.mask.beforefirst.v2i1(<2 x i1> poison)
-; CHECK-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %11 = call <4 x i1> @llvm.mask.beforefirst.v4i1(<4 x i1> poison)
-; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %12 = call <8 x i1> @llvm.mask.beforefirst.v8i1(<8 x i1> poison)
-; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %13 = call <16 x i1> @llvm.mask.beforefirst.v16i1(<16 x i1> poison)
-; CHECK-NEXT: Cost Model: Found an estimated cost of 99 for instruction: %14 = call <32 x i1> @llvm.mask.beforefirst.v32i1(<32 x i1> poison)
-; CHECK-NEXT: Cost Model: Found an estimated cost of 199 for instruction: %15 = call <64 x i1> @llvm.mask.beforefirst.v64i1(<64 x i1> poison)
-; CHECK-NEXT: Cost Model: Found an estimated cost of 399 for instruction: %16 = call <128 x i1> @llvm.mask.beforefirst.v128i1(<128 x i1> poison)
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %1 = call <vscale x 1 x i1> @llvm.mask.beforefirst.nxv1i1(<vscale x 1 x i1> poison)
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %2 = call <vscale x 2 x i1> @llvm.mask.beforefirst.nxv2i1(<vscale x 2 x i1> poison)
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %3 = call <vscale x 4 x i1> @llvm.mask.beforefirst.nxv4i1(<vscale x 4 x i1> poison)
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = call <vscale x 8 x i1> @llvm.mask.beforefirst.nxv8i1(<vscale x 8 x i1> poison)
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %5 = call <vscale x 16 x i1> @llvm.mask.beforefirst.nxv16i1(<vscale x 16 x i1> poison)
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %6 = call <vscale x 32 x i1> @llvm.mask.beforefirst.nxv32i1(<vscale x 32 x i1> poison)
+; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %7 = call <vscale x 64 x i1> @llvm.mask.beforefirst.nxv64i1(<vscale x 64 x i1> poison)
+; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %8 = call <vscale x 128 x i1> @llvm.mask.beforefirst.nxv128i1(<vscale x 128 x i1> poison)
+; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %9 = call <1 x i1> @llvm.mask.beforefirst.v1i1(<1 x i1> poison)
+; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %10 = call <2 x i1> @llvm.mask.beforefirst.v2i1(<2 x i1> poison)
+; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %11 = call <4 x i1> @llvm.mask.beforefirst.v4i1(<4 x i1> poison)
+; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %12 = call <8 x i1> @llvm.mask.beforefirst.v8i1(<8 x i1> poison)
+; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %13 = call <16 x i1> @llvm.mask.beforefirst.v16i1(<16 x i1> poison)
+; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %14 = call <32 x i1> @llvm.mask.beforefirst.v32i1(<32 x i1> poison)
+; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %15 = call <64 x i1> @llvm.mask.beforefirst.v64i1(<64 x i1> poison)
+; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %16 = call <128 x i1> @llvm.mask.beforefirst.v128i1(<128 x i1> poison)
; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void
;
call <vscale x 1 x i1> @llvm.mask.beforefirst(<vscale x 1 x i1> poison)
>From 88680512d22490a98eeb9212147a83236ec213f4 Mon Sep 17 00:00:00 2001
From: Luke Lau <luke at igalia.com>
Date: Thu, 22 Oct 2026 10:24:50 +0800
Subject: [PATCH 3/3] Handle scalarization
---
llvm/include/llvm/CodeGen/BasicTTIImpl.h | 6 +++++
.../CostModel/AArch64/mask-beforefirst.ll | 23 +++++++++++--------
2 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/BasicTTIImpl.h b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
index 54f61e0d55c4da..6311f5437dbbbc 100644
--- a/llvm/include/llvm/CodeGen/BasicTTIImpl.h
+++ b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
@@ -2690,6 +2690,12 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
if (!getTLI()->isOperationExpand(ISD, LT.second))
break;
+ // Scalar types are lowered as a not.
+ if (!LT.second.isVector())
+ return LT.first *
+ thisT()->getArithmeticInstrCost(
+ Instruction::Xor, RetTy->getScalarType(), CostKind);
+
// Expansion via (get_active_lane_mask 0, (cttz.elts mask))
RetTy = VectorType::get(RetTy->getScalarType(),
LT.second.getVectorElementCount());
diff --git a/llvm/test/Analysis/CostModel/AArch64/mask-beforefirst.ll b/llvm/test/Analysis/CostModel/AArch64/mask-beforefirst.ll
index 48a6200141be03..77480dff9ece80 100644
--- a/llvm/test/Analysis/CostModel/AArch64/mask-beforefirst.ll
+++ b/llvm/test/Analysis/CostModel/AArch64/mask-beforefirst.ll
@@ -9,11 +9,12 @@ define void @mask_beforefirst() {
; SVE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %3 = call <vscale x 8 x i1> @llvm.mask.beforefirst.nxv8i1(<vscale x 8 x i1> poison)
; SVE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = call <vscale x 16 x i1> @llvm.mask.beforefirst.nxv16i1(<vscale x 16 x i1> poison)
; SVE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %5 = call <vscale x 32 x i1> @llvm.mask.beforefirst.nxv32i1(<vscale x 32 x i1> poison)
-; SVE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %6 = call <2 x i1> @llvm.mask.beforefirst.v2i1(<2 x i1> poison)
-; SVE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %7 = call <4 x i1> @llvm.mask.beforefirst.v4i1(<4 x i1> poison)
-; SVE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %8 = call <8 x i1> @llvm.mask.beforefirst.v8i1(<8 x i1> poison)
-; SVE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %9 = call <16 x i1> @llvm.mask.beforefirst.v16i1(<16 x i1> poison)
-; SVE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %10 = call <32 x i1> @llvm.mask.beforefirst.v32i1(<32 x i1> poison)
+; SVE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %6 = call <1 x i1> @llvm.mask.beforefirst.v1i1(<1 x i1> poison)
+; SVE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %7 = call <2 x i1> @llvm.mask.beforefirst.v2i1(<2 x i1> poison)
+; SVE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %8 = call <4 x i1> @llvm.mask.beforefirst.v4i1(<4 x i1> poison)
+; SVE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %9 = call <8 x i1> @llvm.mask.beforefirst.v8i1(<8 x i1> poison)
+; SVE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %10 = call <16 x i1> @llvm.mask.beforefirst.v16i1(<16 x i1> poison)
+; SVE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %11 = call <32 x i1> @llvm.mask.beforefirst.v32i1(<32 x i1> poison)
; SVE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void
;
; NEON-LABEL: 'mask_beforefirst'
@@ -22,11 +23,12 @@ define void @mask_beforefirst() {
; NEON-NEXT: Cost Model: Invalid cost for instruction: %3 = call <vscale x 8 x i1> @llvm.mask.beforefirst.nxv8i1(<vscale x 8 x i1> poison)
; NEON-NEXT: Cost Model: Invalid cost for instruction: %4 = call <vscale x 16 x i1> @llvm.mask.beforefirst.nxv16i1(<vscale x 16 x i1> poison)
; NEON-NEXT: Cost Model: Invalid cost for instruction: %5 = call <vscale x 32 x i1> @llvm.mask.beforefirst.nxv32i1(<vscale x 32 x i1> poison)
-; NEON-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %6 = call <2 x i1> @llvm.mask.beforefirst.v2i1(<2 x i1> poison)
-; NEON-NEXT: Cost Model: Found an estimated cost of 20 for instruction: %7 = call <4 x i1> @llvm.mask.beforefirst.v4i1(<4 x i1> poison)
-; NEON-NEXT: Cost Model: Found an estimated cost of 40 for instruction: %8 = call <8 x i1> @llvm.mask.beforefirst.v8i1(<8 x i1> poison)
-; NEON-NEXT: Cost Model: Found an estimated cost of 80 for instruction: %9 = call <16 x i1> @llvm.mask.beforefirst.v16i1(<16 x i1> poison)
-; NEON-NEXT: Cost Model: Found an estimated cost of 160 for instruction: %10 = call <32 x i1> @llvm.mask.beforefirst.v32i1(<32 x i1> poison)
+; NEON-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %6 = call <1 x i1> @llvm.mask.beforefirst.v1i1(<1 x i1> poison)
+; NEON-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %7 = call <2 x i1> @llvm.mask.beforefirst.v2i1(<2 x i1> poison)
+; NEON-NEXT: Cost Model: Found an estimated cost of 20 for instruction: %8 = call <4 x i1> @llvm.mask.beforefirst.v4i1(<4 x i1> poison)
+; NEON-NEXT: Cost Model: Found an estimated cost of 40 for instruction: %9 = call <8 x i1> @llvm.mask.beforefirst.v8i1(<8 x i1> poison)
+; NEON-NEXT: Cost Model: Found an estimated cost of 80 for instruction: %10 = call <16 x i1> @llvm.mask.beforefirst.v16i1(<16 x i1> poison)
+; NEON-NEXT: Cost Model: Found an estimated cost of 160 for instruction: %11 = call <32 x i1> @llvm.mask.beforefirst.v32i1(<32 x i1> poison)
; NEON-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void
;
call <vscale x 2 x i1> @llvm.mask.beforefirst(<vscale x 2 x i1> poison)
@@ -34,6 +36,7 @@ define void @mask_beforefirst() {
call <vscale x 8 x i1> @llvm.mask.beforefirst(<vscale x 8 x i1> poison)
call <vscale x 16 x i1> @llvm.mask.beforefirst(<vscale x 16 x i1> poison)
call <vscale x 32 x i1> @llvm.mask.beforefirst(<vscale x 32 x i1> poison)
+ call <1 x i1> @llvm.mask.beforefirst(<1 x i1> poison)
call <2 x i1> @llvm.mask.beforefirst(<2 x i1> poison)
call <4 x i1> @llvm.mask.beforefirst(<4 x i1> poison)
call <8 x i1> @llvm.mask.beforefirst(<8 x i1> poison)
More information about the llvm-branch-commits
mailing list