[llvm] [LLVM][InstCombine][SVE] Canonicalise sve.ptrue(SV_POW2) to splat(i1 true). (PR #203556)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 12 08:09:00 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-aarch64
Author: Paul Walker (paulwalker-arm)
<details>
<summary>Changes</summary>
SVE vectors must be a power-of-two in length, making pow2 synonymous with all.
NOTE: I wasn't sure about the intent of the tests in sve-intrinsics-ptest.ll but figured `0 (SV_POW2)` is being used as a proxy for `!= 31` and so changed it to something else that ensures the output IR matches the input. Given I had to edit the test I decided to remove the redundant function declarations.
---
Full diff: https://github.com/llvm/llvm-project/pull/203556.diff
3 Files Affected:
- (modified) llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp (+5-2)
- (added) llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-ptrue.ll (+157)
- (modified) llvm/test/Transforms/InstCombine/AArch64/sve-intrinsics-ptest.ll (+6-33)
``````````diff
diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
index 71077846088a2..38a76b45bdabb 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
@@ -2967,8 +2967,11 @@ static std::optional<Instruction *> instCombineWhilelo(InstCombiner &IC,
static std::optional<Instruction *> instCombinePTrue(InstCombiner &IC,
IntrinsicInst &II) {
- if (match(II.getOperand(0), m_ConstantInt<AArch64SVEPredPattern::all>()))
- return IC.replaceInstUsesWith(II, Constant::getAllOnesValue(II.getType()));
+ unsigned PredPattern = cast<ConstantInt>(II.getOperand(0))->getZExtValue();
+ // SVE vector length is a power-of-two, thus pow2 is synonymous with all.
+ if (PredPattern == AArch64SVEPredPattern::all ||
+ PredPattern == AArch64SVEPredPattern::pow2)
+ return IC.replaceInstUsesWith(II, ConstantInt::getTrue(II.getType()));
return std::nullopt;
}
diff --git a/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-ptrue.ll b/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-ptrue.ll
new file mode 100644
index 0000000000000..826d8ba3823ed
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-ptrue.ll
@@ -0,0 +1,157 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -passes=instcombine < %s | FileCheck %s
+
+target triple = "aarch64-unknown-linux-gnu"
+
+define <vscale x 16 x i1> @ptrue_pow2(<vscale x 16 x i1> %a) #0 {
+; CHECK-LABEL: @ptrue_pow2(
+; CHECK-NEXT: ret <vscale x 16 x i1> splat (i1 true)
+;
+ %mask = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue(i32 0)
+ ret <vscale x 16 x i1> %mask
+}
+
+define <vscale x 16 x i1> @ptrue_vl1(<vscale x 16 x i1> %a) #0 {
+; CHECK-LABEL: @ptrue_vl1(
+; CHECK-NEXT: [[MASK:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue.nxv16i1(i32 1)
+; CHECK-NEXT: ret <vscale x 16 x i1> [[MASK]]
+;
+ %mask = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue(i32 1)
+ ret <vscale x 16 x i1> %mask
+}
+
+define <vscale x 16 x i1> @ptrue_vl2(<vscale x 16 x i1> %a) #0 {
+; CHECK-LABEL: @ptrue_vl2(
+; CHECK-NEXT: [[MASK:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue.nxv16i1(i32 2)
+; CHECK-NEXT: ret <vscale x 16 x i1> [[MASK]]
+;
+ %mask = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue(i32 2)
+ ret <vscale x 16 x i1> %mask
+}
+
+define <vscale x 16 x i1> @ptrue_vl3(<vscale x 16 x i1> %a) #0 {
+; CHECK-LABEL: @ptrue_vl3(
+; CHECK-NEXT: [[MASK:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue.nxv16i1(i32 3)
+; CHECK-NEXT: ret <vscale x 16 x i1> [[MASK]]
+;
+ %mask = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue(i32 3)
+ ret <vscale x 16 x i1> %mask
+}
+
+define <vscale x 16 x i1> @ptrue_vl4(<vscale x 16 x i1> %a) #0 {
+; CHECK-LABEL: @ptrue_vl4(
+; CHECK-NEXT: [[MASK:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue.nxv16i1(i32 4)
+; CHECK-NEXT: ret <vscale x 16 x i1> [[MASK]]
+;
+ %mask = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue(i32 4)
+ ret <vscale x 16 x i1> %mask
+}
+
+define <vscale x 16 x i1> @ptrue_vl5(<vscale x 16 x i1> %a) #0 {
+; CHECK-LABEL: @ptrue_vl5(
+; CHECK-NEXT: [[MASK:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue.nxv16i1(i32 5)
+; CHECK-NEXT: ret <vscale x 16 x i1> [[MASK]]
+;
+ %mask = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue(i32 5)
+ ret <vscale x 16 x i1> %mask
+}
+
+define <vscale x 16 x i1> @ptrue_vl6(<vscale x 16 x i1> %a) #0 {
+; CHECK-LABEL: @ptrue_vl6(
+; CHECK-NEXT: [[MASK:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue.nxv16i1(i32 6)
+; CHECK-NEXT: ret <vscale x 16 x i1> [[MASK]]
+;
+ %mask = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue(i32 6)
+ ret <vscale x 16 x i1> %mask
+}
+
+define <vscale x 16 x i1> @ptrue_vl7(<vscale x 16 x i1> %a) #0 {
+; CHECK-LABEL: @ptrue_vl7(
+; CHECK-NEXT: [[MASK:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue.nxv16i1(i32 7)
+; CHECK-NEXT: ret <vscale x 16 x i1> [[MASK]]
+;
+ %mask = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue(i32 7)
+ ret <vscale x 16 x i1> %mask
+}
+
+define <vscale x 16 x i1> @ptrue_vl8(<vscale x 16 x i1> %a) #0 {
+; CHECK-LABEL: @ptrue_vl8(
+; CHECK-NEXT: [[MASK:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue.nxv16i1(i32 8)
+; CHECK-NEXT: ret <vscale x 16 x i1> [[MASK]]
+;
+ %mask = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue(i32 8)
+ ret <vscale x 16 x i1> %mask
+}
+
+define <vscale x 16 x i1> @ptrue_vl16(<vscale x 16 x i1> %a) #0 {
+; CHECK-LABEL: @ptrue_vl16(
+; CHECK-NEXT: [[MASK:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue.nxv16i1(i32 9)
+; CHECK-NEXT: ret <vscale x 16 x i1> [[MASK]]
+;
+ %mask = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue(i32 9)
+ ret <vscale x 16 x i1> %mask
+}
+
+define <vscale x 16 x i1> @ptrue_vl32(<vscale x 16 x i1> %a) #0 {
+; CHECK-LABEL: @ptrue_vl32(
+; CHECK-NEXT: [[MASK:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue.nxv16i1(i32 10)
+; CHECK-NEXT: ret <vscale x 16 x i1> [[MASK]]
+;
+ %mask = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue(i32 10)
+ ret <vscale x 16 x i1> %mask
+}
+
+define <vscale x 16 x i1> @ptrue_vl64(<vscale x 16 x i1> %a) #0 {
+; CHECK-LABEL: @ptrue_vl64(
+; CHECK-NEXT: [[MASK:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue.nxv16i1(i32 11)
+; CHECK-NEXT: ret <vscale x 16 x i1> [[MASK]]
+;
+ %mask = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue(i32 11)
+ ret <vscale x 16 x i1> %mask
+}
+
+define <vscale x 16 x i1> @ptrue_vl128(<vscale x 16 x i1> %a) #0 {
+; CHECK-LABEL: @ptrue_vl128(
+; CHECK-NEXT: [[MASK:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue.nxv16i1(i32 12)
+; CHECK-NEXT: ret <vscale x 16 x i1> [[MASK]]
+;
+ %mask = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue(i32 12)
+ ret <vscale x 16 x i1> %mask
+}
+
+define <vscale x 16 x i1> @ptrue_vl256(<vscale x 16 x i1> %a) #0 {
+; CHECK-LABEL: @ptrue_vl256(
+; CHECK-NEXT: [[MASK:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue.nxv16i1(i32 13)
+; CHECK-NEXT: ret <vscale x 16 x i1> [[MASK]]
+;
+ %mask = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue(i32 13)
+ ret <vscale x 16 x i1> %mask
+}
+
+define <vscale x 16 x i1> @ptrue_mul4(<vscale x 16 x i1> %a) #0 {
+; CHECK-LABEL: @ptrue_mul4(
+; CHECK-NEXT: [[MASK:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue.nxv16i1(i32 29)
+; CHECK-NEXT: ret <vscale x 16 x i1> [[MASK]]
+;
+ %mask = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue(i32 29)
+ ret <vscale x 16 x i1> %mask
+}
+
+define <vscale x 16 x i1> @ptrue_mul3(<vscale x 16 x i1> %a) #0 {
+; CHECK-LABEL: @ptrue_mul3(
+; CHECK-NEXT: [[MASK:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue.nxv16i1(i32 30)
+; CHECK-NEXT: ret <vscale x 16 x i1> [[MASK]]
+;
+ %mask = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue(i32 30)
+ ret <vscale x 16 x i1> %mask
+}
+
+define <vscale x 16 x i1> @ptrue_all(<vscale x 16 x i1> %a) #0 {
+; CHECK-LABEL: @ptrue_all(
+; CHECK-NEXT: ret <vscale x 16 x i1> splat (i1 true)
+;
+ %mask = tail call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue(i32 31)
+ ret <vscale x 16 x i1> %mask
+}
+
+attributes #0 = { "target-features"="+sve" }
diff --git a/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsics-ptest.ll b/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsics-ptest.ll
index e00ad68bdfacf..20dccf52ca7de 100644
--- a/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsics-ptest.ll
+++ b/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsics-ptest.ll
@@ -25,11 +25,11 @@ define i1 @ptest_last_to_any(<vscale x 16 x i1> %a) #0 {
define i1 @ptest_any1(<vscale x 2 x i1> %a) #0 {
; CHECK-LABEL: @ptest_any1(
-; CHECK-NEXT: [[MASK:%.*]] = tail call <vscale x 2 x i1> @llvm.aarch64.sve.ptrue.nxv2i1(i32 0)
+; CHECK-NEXT: [[MASK:%.*]] = tail call <vscale x 2 x i1> @llvm.aarch64.sve.ptrue.nxv2i1(i32 30)
; CHECK-NEXT: [[OUT:%.*]] = call i1 @llvm.aarch64.sve.ptest.any.nxv2i1(<vscale x 2 x i1> [[MASK]], <vscale x 2 x i1> [[A:%.*]])
; CHECK-NEXT: ret i1 [[OUT]]
;
- %mask = tail call <vscale x 2 x i1> @llvm.aarch64.sve.ptrue.nxv2i1(i32 0)
+ %mask = tail call <vscale x 2 x i1> @llvm.aarch64.sve.ptrue.nxv2i1(i32 30)
%1 = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv2i1(<vscale x 2 x i1> %mask)
%2 = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv2i1(<vscale x 2 x i1> %a)
%out = call i1 @llvm.aarch64.sve.ptest.any.nxv16i1(<vscale x 16 x i1> %1, <vscale x 16 x i1> %2)
@@ -53,11 +53,11 @@ define i1 @ptest_any2(<vscale x 4 x i1> %a) #0 {
define i1 @ptest_first(<vscale x 4 x i1> %a) #0 {
; CHECK-LABEL: @ptest_first(
-; CHECK-NEXT: [[MASK:%.*]] = tail call <vscale x 4 x i1> @llvm.aarch64.sve.ptrue.nxv4i1(i32 0)
+; CHECK-NEXT: [[MASK:%.*]] = tail call <vscale x 4 x i1> @llvm.aarch64.sve.ptrue.nxv4i1(i32 30)
; CHECK-NEXT: [[OUT:%.*]] = call i1 @llvm.aarch64.sve.ptest.first.nxv4i1(<vscale x 4 x i1> [[MASK]], <vscale x 4 x i1> [[A:%.*]])
; CHECK-NEXT: ret i1 [[OUT]]
;
- %mask = tail call <vscale x 4 x i1> @llvm.aarch64.sve.ptrue.nxv4i1(i32 0)
+ %mask = tail call <vscale x 4 x i1> @llvm.aarch64.sve.ptrue.nxv4i1(i32 30)
%1 = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv4i1(<vscale x 4 x i1> %mask)
%2 = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv4i1(<vscale x 4 x i1> %a)
%out = call i1 @llvm.aarch64.sve.ptest.first.nxv16i1(<vscale x 16 x i1> %1, <vscale x 16 x i1> %2)
@@ -76,11 +76,11 @@ define i1 @ptest_first_same_ops(<vscale x 2 x i1> %a) #0 {
define i1 @ptest_last(<vscale x 8 x i1> %a) #0 {
; CHECK-LABEL: @ptest_last(
-; CHECK-NEXT: [[MASK:%.*]] = tail call <vscale x 8 x i1> @llvm.aarch64.sve.ptrue.nxv8i1(i32 0)
+; CHECK-NEXT: [[MASK:%.*]] = tail call <vscale x 8 x i1> @llvm.aarch64.sve.ptrue.nxv8i1(i32 30)
; CHECK-NEXT: [[OUT:%.*]] = call i1 @llvm.aarch64.sve.ptest.last.nxv8i1(<vscale x 8 x i1> [[MASK]], <vscale x 8 x i1> [[A:%.*]])
; CHECK-NEXT: ret i1 [[OUT]]
;
- %mask = tail call <vscale x 8 x i1> @llvm.aarch64.sve.ptrue.nxv8i1(i32 0)
+ %mask = tail call <vscale x 8 x i1> @llvm.aarch64.sve.ptrue.nxv8i1(i32 30)
%1 = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> %mask)
%2 = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> %a)
%out = call i1 @llvm.aarch64.sve.ptest.last.nxv16i1(<vscale x 16 x i1> %1, <vscale x 16 x i1> %2)
@@ -221,31 +221,4 @@ define i1 @ptest_any_orr_z(<vscale x 16 x i1> %pg, <vscale x 16 x i1> %a, <vscal
ret i1 %2
}
-declare <vscale x 16 x i1> @llvm.aarch64.sve.ptrue.nxv16i1(i32)
-declare <vscale x 8 x i1> @llvm.aarch64.sve.ptrue.nxv8i1(i32)
-declare <vscale x 4 x i1> @llvm.aarch64.sve.ptrue.nxv4i1(i32)
-declare <vscale x 2 x i1> @llvm.aarch64.sve.ptrue.nxv2i1(i32)
-
-declare i1 @llvm.aarch64.sve.ptest.any.nxv16i1(<vscale x 16 x i1>, <vscale x 16 x i1>)
-declare i1 @llvm.aarch64.sve.ptest.first.nxv16i1(<vscale x 16 x i1>, <vscale x 16 x i1>)
-declare i1 @llvm.aarch64.sve.ptest.last.nxv16i1(<vscale x 16 x i1>, <vscale x 16 x i1>)
-
-declare <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1>)
-declare <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv4i1(<vscale x 4 x i1>)
-declare <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv2i1(<vscale x 2 x i1>)
-
-declare <vscale x 16 x i1> @llvm.aarch64.sve.brka.z.nxv16i1(<vscale x 16 x i1>, <vscale x 16 x i1>)
-declare <vscale x 16 x i1> @llvm.aarch64.sve.brkb.z.nxv16i1(<vscale x 16 x i1>, <vscale x 16 x i1>)
-declare <vscale x 16 x i1> @llvm.aarch64.sve.brkpa.z.nxv16i1(<vscale x 16 x i1>, <vscale x 16 x i1>, <vscale x 16 x i1>)
-declare <vscale x 16 x i1> @llvm.aarch64.sve.brkpb.z.nxv16i1(<vscale x 16 x i1>, <vscale x 16 x i1>, <vscale x 16 x i1>)
-declare <vscale x 16 x i1> @llvm.aarch64.sve.rdffr.z(<vscale x 16 x i1>)
-
-declare <vscale x 16 x i1> @llvm.aarch64.sve.and.z.nxv16i1(<vscale x 16 x i1>, <vscale x 16 x i1>, <vscale x 16 x i1>)
-declare <vscale x 16 x i1> @llvm.aarch64.sve.bic.z.nxv16i1(<vscale x 16 x i1>, <vscale x 16 x i1>, <vscale x 16 x i1>)
-declare <vscale x 16 x i1> @llvm.aarch64.sve.eor.z.nxv16i1(<vscale x 16 x i1>, <vscale x 16 x i1>, <vscale x 16 x i1>)
-declare <vscale x 16 x i1> @llvm.aarch64.sve.nand.z.nxv16i1(<vscale x 16 x i1>, <vscale x 16 x i1>, <vscale x 16 x i1>)
-declare <vscale x 16 x i1> @llvm.aarch64.sve.nor.z.nxv16i1(<vscale x 16 x i1>, <vscale x 16 x i1>, <vscale x 16 x i1>)
-declare <vscale x 16 x i1> @llvm.aarch64.sve.orn.z.nxv16i1(<vscale x 16 x i1>, <vscale x 16 x i1>, <vscale x 16 x i1>)
-declare <vscale x 16 x i1> @llvm.aarch64.sve.orr.z.nxv16i1(<vscale x 16 x i1>, <vscale x 16 x i1>, <vscale x 16 x i1>)
-
attributes #0 = { "target-features"="+sve" }
``````````
</details>
https://github.com/llvm/llvm-project/pull/203556
More information about the llvm-commits
mailing list