[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