[llvm] d5f6426 - [AArch64][SVE] Optimize logical ops with convert.to.svbool (#160408)

via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 11 05:07:02 PDT 2026


Author: Vladimir Miloserdov
Date: 2026-09-11T13:06:57+01:00
New Revision: d5f6426a52af4966bd6902634648ba40c23bdc35

URL: https://github.com/llvm/llvm-project/commit/d5f6426a52af4966bd6902634648ba40c23bdc35
DIFF: https://github.com/llvm/llvm-project/commit/d5f6426a52af4966bd6902634648ba40c23bdc35.diff

LOG: [AArch64][SVE] Optimize logical ops with convert.to.svbool (#160408)

When both operands of a logical operation (and/or/xor) are
convert.to.svbool
from the same narrower type, unwrap to that type, simplify using
simplifyBinOp,
and rewrap the result. This eliminates redundant instructions in cases
like:
 svand_z(svptrue_b8(), svpnext_b16(prev, pg), svptrue_b16());

Fixes https://github.com/llvm/llvm-project/issues/160279.

---------

Co-authored-by: Paul Walker <paul.walker at arm.com>

Added: 
    llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-and-or-with-all-true.ll

Modified: 
    llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
index d872c2ec34c25..d8e8f58291a8d 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
@@ -2022,6 +2022,34 @@ simplifySVEIntrinsicBinOp(InstCombiner &IC, IntrinsicInst &II,
   else
     SimpleII = simplifyBinOp(Opc, Op1, Op2, DL);
 
+  // If both operands are convert.to.svbool from the same narrower predicate
+  // type, try to simplify the operation at that narrower type. This is valid
+  // because the conversions zero the lanes not represented by the narrower
+  // type, so those lanes of the result are zero either way.
+  Value *NarrowOp1, *NarrowOp2;
+  if (!SimpleII &&
+      match(Op1, m_Intrinsic<Intrinsic::aarch64_sve_convert_to_svbool>(
+                     m_Value(NarrowOp1))) &&
+      match(Op2, m_Intrinsic<Intrinsic::aarch64_sve_convert_to_svbool>(
+                     m_Value(NarrowOp2))) &&
+      NarrowOp1->getType() == NarrowOp2->getType() &&
+      NarrowOp1->getType()->isScalableTy() &&
+      NarrowOp1->getType()->isIntOrIntVectorTy(1)) {
+    Value *SimpleNarrow = simplifyBinOp(Opc, NarrowOp1, NarrowOp2, DL);
+    if (SimpleNarrow && !isa<UndefValue>(SimpleNarrow)) {
+      if (match(SimpleNarrow, m_ZeroInt()))
+        SimpleII = Constant::getNullValue(II.getType());
+      else if (SimpleNarrow == NarrowOp1)
+        SimpleII = Op1;
+      else if (SimpleNarrow == NarrowOp2)
+        SimpleII = Op2;
+      else
+        SimpleII = IC.Builder.CreateIntrinsic(
+            Intrinsic::aarch64_sve_convert_to_svbool, {SimpleNarrow->getType()},
+            {SimpleNarrow});
+    }
+  }
+
   // An SVE intrinsic's result is always defined. However, this is not the case
   // for its equivalent IR instruction (e.g. when shifting by an amount more
   // than the data's bitwidth). Simplifications to an undefined result must be

diff  --git a/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-and-or-with-all-true.ll b/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-and-or-with-all-true.ll
new file mode 100644
index 0000000000000..1305765fcb641
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-and-or-with-all-true.ll
@@ -0,0 +1,264 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=instcombine < %s | FileCheck %s
+
+target triple = "aarch64-unknown-linux-gnu"
+
+; Test AArch64-specific InstCombine optimizations for SVE logical operations
+; whose operands are convert.to.svbool from a narrower predicate type.
+; - a AND true = a
+; - a OR true = true
+
+define <vscale x 16 x i1> @test_and_convert_all_true_right_b16(<vscale x 8 x i1> %x) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @test_and_convert_all_true_right_b16(
+; CHECK-SAME: <vscale x 8 x i1> [[X:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:    [[CONV_X:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> [[X]])
+; CHECK-NEXT:    ret <vscale x 16 x i1> [[CONV_X]]
+;
+  %conv_x = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> %x)
+  %conv_true = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> splat (i1 true))
+  %result = tail call <vscale x 16 x i1> @llvm.aarch64.sve.and.z.nxv16i1(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i1> %conv_x, <vscale x 16 x i1> %conv_true)
+  ret <vscale x 16 x i1> %result
+}
+
+define <vscale x 16 x i1> @test_and_convert_all_true_left_b16(<vscale x 8 x i1> %x) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @test_and_convert_all_true_left_b16(
+; CHECK-SAME: <vscale x 8 x i1> [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[CONV_X:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> [[X]])
+; CHECK-NEXT:    ret <vscale x 16 x i1> [[CONV_X]]
+;
+  %conv_x = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> %x)
+  %conv_true = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> splat (i1 true))
+  %result = tail call <vscale x 16 x i1> @llvm.aarch64.sve.and.z.nxv16i1(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i1> %conv_true, <vscale x 16 x i1> %conv_x)
+  ret <vscale x 16 x i1> %result
+}
+
+define <vscale x 16 x i1> @test_orr_convert_all_true_right_b16(<vscale x 8 x i1> %x) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @test_orr_convert_all_true_right_b16(
+; CHECK-SAME: <vscale x 8 x i1> [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[CONV_TRUE:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> splat (i1 true))
+; CHECK-NEXT:    ret <vscale x 16 x i1> [[CONV_TRUE]]
+;
+  %conv_x = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> %x)
+  %conv_true = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> splat (i1 true))
+  %result = tail call <vscale x 16 x i1> @llvm.aarch64.sve.orr.z.nxv16i1(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i1> %conv_x, <vscale x 16 x i1> %conv_true)
+  ret <vscale x 16 x i1> %result
+}
+
+define <vscale x 16 x i1> @test_orr_convert_all_true_left_b16(<vscale x 8 x i1> %x) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @test_orr_convert_all_true_left_b16(
+; CHECK-SAME: <vscale x 8 x i1> [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[CONV_TRUE:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> splat (i1 true))
+; CHECK-NEXT:    ret <vscale x 16 x i1> [[CONV_TRUE]]
+;
+  %conv_x = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> %x)
+  %conv_true = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> splat (i1 true))
+  %result = tail call <vscale x 16 x i1> @llvm.aarch64.sve.orr.z.nxv16i1(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i1> %conv_true, <vscale x 16 x i1> %conv_x)
+  ret <vscale x 16 x i1> %result
+}
+
+define <vscale x 16 x i1> @test_and_convert_all_true_b32(<vscale x 4 x i1> %x) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @test_and_convert_all_true_b32(
+; CHECK-SAME: <vscale x 4 x i1> [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[CONV_X:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv4i1(<vscale x 4 x i1> [[X]])
+; CHECK-NEXT:    ret <vscale x 16 x i1> [[CONV_X]]
+;
+  %conv_x = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv4i1(<vscale x 4 x i1> %x)
+  %conv_true = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv4i1(<vscale x 4 x i1> splat (i1 true))
+  %result = tail call <vscale x 16 x i1> @llvm.aarch64.sve.and.z.nxv16i1(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i1> %conv_x, <vscale x 16 x i1> %conv_true)
+  ret <vscale x 16 x i1> %result
+}
+
+define <vscale x 16 x i1> @test_and_convert_all_true_b64(<vscale x 2 x i1> %x) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @test_and_convert_all_true_b64(
+; CHECK-SAME: <vscale x 2 x i1> [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[CONV_X:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv2i1(<vscale x 2 x i1> [[X]])
+; CHECK-NEXT:    ret <vscale x 16 x i1> [[CONV_X]]
+;
+  %conv_x = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv2i1(<vscale x 2 x i1> %x)
+  %conv_true = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv2i1(<vscale x 2 x i1> splat (i1 true))
+  %result = tail call <vscale x 16 x i1> @llvm.aarch64.sve.and.z.nxv16i1(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i1> %conv_x, <vscale x 16 x i1> %conv_true)
+  ret <vscale x 16 x i1> %result
+}
+
+; Reproducer from https://github.com/llvm/llvm-project/issues/160279.
+define <vscale x 16 x i1> @test_and_pnext_ptrue_b16(<vscale x 16 x i1> %pg, <vscale x 16 x i1> %prev) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @test_and_pnext_ptrue_b16(
+; CHECK-SAME: <vscale x 16 x i1> [[PG:%.*]], <vscale x 16 x i1> [[PREV:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call <vscale x 8 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> [[PREV]])
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call <vscale x 8 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> [[PG]])
+; CHECK-NEXT:    [[TMP3:%.*]] = tail call <vscale x 8 x i1> @llvm.aarch64.sve.pnext.nxv8i1(<vscale x 8 x i1> [[TMP1]], <vscale x 8 x i1> [[TMP2]])
+; CHECK-NEXT:    [[TMP4:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> [[TMP3]])
+; CHECK-NEXT:    ret <vscale x 16 x i1> [[TMP4]]
+;
+  %1 = tail call <vscale x 8 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %prev)
+  %2 = tail call <vscale x 8 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+  %3 = tail call <vscale x 8 x i1> @llvm.aarch64.sve.pnext.nxv8i1(<vscale x 8 x i1> %1, <vscale x 8 x i1> %2)
+  %4 = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> %3)
+  %5 = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> splat (i1 true))
+  %6 = tail call <vscale x 16 x i1> @llvm.aarch64.sve.and.z.nxv16i1(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i1> %4, <vscale x 16 x i1> %5)
+  ret <vscale x 16 x i1> %6
+}
+
+define <vscale x 16 x i1> @test_eor_convert_same(<vscale x 8 x i1> %x) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @test_eor_convert_same(
+; CHECK-SAME: <vscale x 8 x i1> [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    ret <vscale x 16 x i1> zeroinitializer
+;
+  %conv_x = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> %x)
+  %result = tail call <vscale x 16 x i1> @llvm.aarch64.sve.eor.z.nxv16i1(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i1> %conv_x, <vscale x 16 x i1> %conv_x)
+  ret <vscale x 16 x i1> %result
+}
+
+define <vscale x 16 x i1> @test_eor_convert_zero(<vscale x 8 x i1> %x) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @test_eor_convert_zero(
+; CHECK-SAME: <vscale x 8 x i1> [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[CONV_X:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> [[X]])
+; CHECK-NEXT:    ret <vscale x 16 x i1> [[CONV_X]]
+;
+  %conv_x = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> %x)
+  %conv_zero = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> zeroinitializer)
+  %result = tail call <vscale x 16 x i1> @llvm.aarch64.sve.eor.z.nxv16i1(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i1> %conv_x, <vscale x 16 x i1> %conv_zero)
+  ret <vscale x 16 x i1> %result
+}
+
+define <vscale x 16 x i1> @test_and_convert_zero(<vscale x 8 x i1> %x) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @test_and_convert_zero(
+; CHECK-SAME: <vscale x 8 x i1> [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    ret <vscale x 16 x i1> zeroinitializer
+;
+  %conv_x = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> %x)
+  %conv_zero = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> zeroinitializer)
+  %result = tail call <vscale x 16 x i1> @llvm.aarch64.sve.and.z.nxv16i1(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i1> %conv_x, <vscale x 16 x i1> %conv_zero)
+  ret <vscale x 16 x i1> %result
+}
+
+define <vscale x 16 x i1> @test_orr_convert_zero(<vscale x 8 x i1> %x) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @test_orr_convert_zero(
+; CHECK-SAME: <vscale x 8 x i1> [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[CONV_X:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> [[X]])
+; CHECK-NEXT:    ret <vscale x 16 x i1> [[CONV_X]]
+;
+  %conv_x = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> %x)
+  %conv_zero = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> zeroinitializer)
+  %result = tail call <vscale x 16 x i1> @llvm.aarch64.sve.orr.z.nxv16i1(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i1> %conv_x, <vscale x 16 x i1> %conv_zero)
+  ret <vscale x 16 x i1> %result
+}
+
+define <vscale x 16 x i1> @test_orr_convert_complement(<vscale x 8 x i1> %x) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @test_orr_convert_complement(
+; CHECK-SAME: <vscale x 8 x i1> [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[TMP1:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> splat (i1 true))
+; CHECK-NEXT:    ret <vscale x 16 x i1> [[TMP1]]
+;
+  %not_x = xor <vscale x 8 x i1> %x, splat (i1 true)
+  %conv_x = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> %x)
+  %conv_not_x = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> %not_x)
+  %result = tail call <vscale x 16 x i1> @llvm.aarch64.sve.orr.z.nxv16i1(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i1> %conv_x, <vscale x 16 x i1> %conv_not_x)
+  ret <vscale x 16 x i1> %result
+}
+
+define { <vscale x 16 x i1>, <vscale x 16 x i1> } @test_and_convert_multiuse(<vscale x 8 x i1> %x) #0 {
+; CHECK-LABEL: define { <vscale x 16 x i1>, <vscale x 16 x i1> } @test_and_convert_multiuse(
+; CHECK-SAME: <vscale x 8 x i1> [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[CONV_X:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> [[X]])
+; CHECK-NEXT:    [[RET0:%.*]] = insertvalue { <vscale x 16 x i1>, <vscale x 16 x i1> } poison, <vscale x 16 x i1> [[CONV_X]], 0
+; CHECK-NEXT:    [[RET1:%.*]] = insertvalue { <vscale x 16 x i1>, <vscale x 16 x i1> } [[RET0]], <vscale x 16 x i1> [[CONV_X]], 1
+; CHECK-NEXT:    ret { <vscale x 16 x i1>, <vscale x 16 x i1> } [[RET1]]
+;
+  %conv_x = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> %x)
+  %conv_true = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> splat (i1 true))
+  %result = tail call <vscale x 16 x i1> @llvm.aarch64.sve.and.z.nxv16i1(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i1> %conv_x, <vscale x 16 x i1> %conv_true)
+  %ret0 = insertvalue { <vscale x 16 x i1>, <vscale x 16 x i1> } poison, <vscale x 16 x i1> %result, 0
+  %ret1 = insertvalue { <vscale x 16 x i1>, <vscale x 16 x i1> } %ret0, <vscale x 16 x i1> %conv_x, 1
+  ret { <vscale x 16 x i1>, <vscale x 16 x i1> } %ret1
+}
+
+define <vscale x 16 x i1> @test_and_convert_any_predicate(<vscale x 16 x i1> %pred, <vscale x 8 x i1> %x) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @test_and_convert_any_predicate(
+; CHECK-SAME: <vscale x 16 x i1> [[PRED:%.*]], <vscale x 8 x i1> [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[CONV_X:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> [[X]])
+; CHECK-NEXT:    [[RESULT:%.*]] = select <vscale x 16 x i1> [[PRED]], <vscale x 16 x i1> [[CONV_X]], <vscale x 16 x i1> zeroinitializer
+; CHECK-NEXT:    ret <vscale x 16 x i1> [[RESULT]]
+;
+  %conv_x = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> %x)
+  %conv_true = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> splat (i1 true))
+  %result = tail call <vscale x 16 x i1> @llvm.aarch64.sve.and.z.nxv16i1(<vscale x 16 x i1> %pred, <vscale x 16 x i1> %conv_x, <vscale x 16 x i1> %conv_true)
+  ret <vscale x 16 x i1> %result
+}
+
+define <vscale x 16 x i1> @test_and_pg_widened_true(<vscale x 8 x i1> %x) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @test_and_pg_widened_true(
+; CHECK-SAME: <vscale x 8 x i1> [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[PG:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> splat (i1 true))
+; CHECK-NEXT:    [[CONV_X:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> [[X]])
+; CHECK-NEXT:    [[RESULT:%.*]] = select <vscale x 16 x i1> [[PG]], <vscale x 16 x i1> [[CONV_X]], <vscale x 16 x i1> zeroinitializer
+; CHECK-NEXT:    ret <vscale x 16 x i1> [[RESULT]]
+;
+  %pg = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> splat (i1 true))
+  %conv_x = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> %x)
+  %conv_true = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> splat (i1 true))
+  %result = tail call <vscale x 16 x i1> @llvm.aarch64.sve.and.z.nxv16i1(<vscale x 16 x i1> %pg, <vscale x 16 x i1> %conv_x, <vscale x 16 x i1> %conv_true)
+  ret <vscale x 16 x i1> %result
+}
+
+; Negative test
+define <vscale x 16 x i1> @test_eor_convert_all_true(<vscale x 8 x i1> %x) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @test_eor_convert_all_true(
+; CHECK-SAME: <vscale x 8 x i1> [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[CONV_X:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> [[X]])
+; CHECK-NEXT:    [[CONV_TRUE:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> splat (i1 true))
+; CHECK-NEXT:    [[RESULT:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.eor.z.nxv16i1(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i1> [[CONV_X]], <vscale x 16 x i1> [[CONV_TRUE]])
+; CHECK-NEXT:    ret <vscale x 16 x i1> [[RESULT]]
+;
+  %conv_x = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> %x)
+  %conv_true = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> splat (i1 true))
+  %result = tail call <vscale x 16 x i1> @llvm.aarch64.sve.eor.z.nxv16i1(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i1> %conv_x, <vscale x 16 x i1> %conv_true)
+  ret <vscale x 16 x i1> %result
+}
+
+; Negative test
+define <vscale x 16 x i1> @test_and_convert_poison(<vscale x 8 x i1> %x) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @test_and_convert_poison(
+; CHECK-SAME: <vscale x 8 x i1> [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[CONV_X:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> [[X]])
+; CHECK-NEXT:    [[CONV_POISON:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> poison)
+; CHECK-NEXT:    [[RESULT:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.and.z.nxv16i1(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i1> [[CONV_X]], <vscale x 16 x i1> [[CONV_POISON]])
+; CHECK-NEXT:    ret <vscale x 16 x i1> [[RESULT]]
+;
+  %conv_x = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> %x)
+  %conv_poison = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> poison)
+  %result = tail call <vscale x 16 x i1> @llvm.aarch64.sve.and.z.nxv16i1(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i1> %conv_x, <vscale x 16 x i1> %conv_poison)
+  ret <vscale x 16 x i1> %result
+}
+
+; Negative test
+define <vscale x 16 x i1> @test_and_convert_
diff erent_granularities(<vscale x 8 x i1> %x, <vscale x 4 x i1> %y) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @test_and_convert_
diff erent_granularities(
+; CHECK-SAME: <vscale x 8 x i1> [[X:%.*]], <vscale x 4 x i1> [[Y:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[CONV_X:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> [[X]])
+; CHECK-NEXT:    [[CONV_Y:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv4i1(<vscale x 4 x i1> [[Y]])
+; CHECK-NEXT:    [[RESULT:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.and.z.nxv16i1(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i1> [[CONV_X]], <vscale x 16 x i1> [[CONV_Y]])
+; CHECK-NEXT:    ret <vscale x 16 x i1> [[RESULT]]
+;
+  %conv_x = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> %x)
+  %conv_y = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv4i1(<vscale x 4 x i1> %y)
+  %result = tail call <vscale x 16 x i1> @llvm.aarch64.sve.and.z.nxv16i1(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i1> %conv_x, <vscale x 16 x i1> %conv_y)
+  ret <vscale x 16 x i1> %result
+}
+
+; Negative test
+define <vscale x 16 x i1> @test_and_convert_no_all_true(<vscale x 8 x i1> %x, <vscale x 8 x i1> %y) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @test_and_convert_no_all_true(
+; CHECK-SAME: <vscale x 8 x i1> [[X:%.*]], <vscale x 8 x i1> [[Y:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[CONV_X:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> [[X]])
+; CHECK-NEXT:    [[CONV_Y:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> [[Y]])
+; CHECK-NEXT:    [[RESULT:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.and.z.nxv16i1(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i1> [[CONV_X]], <vscale x 16 x i1> [[CONV_Y]])
+; CHECK-NEXT:    ret <vscale x 16 x i1> [[RESULT]]
+;
+  %conv_x = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> %x)
+  %conv_y = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1> %y)
+  %result = tail call <vscale x 16 x i1> @llvm.aarch64.sve.and.z.nxv16i1(<vscale x 16 x i1> splat (i1 true), <vscale x 16 x i1> %conv_x, <vscale x 16 x i1> %conv_y)
+  ret <vscale x 16 x i1> %result
+}
+
+attributes #0 = { "target-features"="+sve" }


        


More information about the llvm-commits mailing list