[llvm-branch-commits] [llvm] [AArch64][TTI] Drop single-use requirement on the mask from BSL sinking (PR #232786)

Valeriy Savchenko via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Oct 16 07:58:39 PDT 2026


https://github.com/SavchenkoValeriy created https://github.com/llvm/llvm-project/pull/232786

Drop the one-use requirement on the mask's Not. Sinking puts a copy of the 
Not next to the And, and the original stays for its other users. 
ISel can then form bsl/bif even when the Not has other uses.

---

<sub>Stack created with <a href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub>

>From 424f205859b03a83f82e21059f24c82bd9e515ab Mon Sep 17 00:00:00 2001
From: Valeriy Savchenko <vsavchenko at apple.com>
Date: Fri, 16 Oct 2026 14:36:47 +0100
Subject: [PATCH 1/2] [AArch64][TTI] Add pre-commit tests (NFC)

---
 llvm/test/CodeGen/AArch64/aarch64-bit-gen.ll  | 45 +++++++++++++++++++
 .../AArch64/sink-free-instructions.ll         | 35 +++++++++++++++
 2 files changed, 80 insertions(+)

diff --git a/llvm/test/CodeGen/AArch64/aarch64-bit-gen.ll b/llvm/test/CodeGen/AArch64/aarch64-bit-gen.ll
index 0dcd4bb159460..09ae5c2dc6590 100644
--- a/llvm/test/CodeGen/AArch64/aarch64-bit-gen.ll
+++ b/llvm/test/CodeGen/AArch64/aarch64-bit-gen.ll
@@ -318,3 +318,48 @@ if.then:
 if.else:
   ret <8 x i8> %b
 }
+
+define <8 x i8> @test_bit_sink_not_after_splat_not_multiuse(<8 x i8> %m, <8 x i8> %b, i8 %s, i1 %c, ptr %p) {
+; CHECK-SD-LABEL: test_bit_sink_not_after_splat_not_multiuse:
+; CHECK-SD:       // %bb.0: // %entry
+; CHECK-SD-NEXT:    fmov d2, d0
+; CHECK-SD-NEXT:    mvn v0.8b, v0.8b
+; CHECK-SD-NEXT:    tbz w1, #0, .LBB13_2
+; CHECK-SD-NEXT:  // %bb.1: // %if.then
+; CHECK-SD-NEXT:    dup v3.8b, w0
+; CHECK-SD-NEXT:    and v1.8b, v2.8b, v1.8b
+; CHECK-SD-NEXT:    bic v0.8b, v0.8b, v3.8b
+; CHECK-SD-NEXT:    orr v0.8b, v1.8b, v0.8b
+; CHECK-SD-NEXT:    str d0, [x2]
+; CHECK-SD-NEXT:  .LBB13_2: // %common.ret
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: test_bit_sink_not_after_splat_not_multiuse:
+; CHECK-GI:       // %bb.0: // %entry
+; CHECK-GI-NEXT:    tbz w1, #0, .LBB13_2
+; CHECK-GI-NEXT:  // %bb.1: // %if.then
+; CHECK-GI-NEXT:    mvn w8, w0
+; CHECK-GI-NEXT:    dup v2.8b, w8
+; CHECK-GI-NEXT:    bsl v0.8b, v1.8b, v2.8b
+; CHECK-GI-NEXT:    str d0, [x2]
+; CHECK-GI-NEXT:    ret
+; CHECK-GI-NEXT:  .LBB13_2:
+; CHECK-GI-NEXT:    mvn v0.8b, v0.8b
+; CHECK-GI-NEXT:    ret
+entry:
+  %n = xor <8 x i8> %m, splat (i8 -1)
+  br i1 %c, label %if.then, label %if.else
+
+if.then:
+  %ns = xor i8 %s, -1
+  %ins = insertelement <8 x i8> poison, i8 %ns, i64 0
+  %spl = shufflevector <8 x i8> %ins, <8 x i8> poison, <8 x i32> zeroinitializer
+  %x = and <8 x i8> %m, %b
+  %y = and <8 x i8> %spl, %n
+  %r = or <8 x i8> %x, %y
+  store <8 x i8> %r, ptr %p
+  ret <8 x i8> %r
+
+if.else:
+  ret <8 x i8> %n
+}
diff --git a/llvm/test/Transforms/CodeGenPrepare/AArch64/sink-free-instructions.ll b/llvm/test/Transforms/CodeGenPrepare/AArch64/sink-free-instructions.ll
index 056237e70a540..680ac477383a0 100644
--- a/llvm/test/Transforms/CodeGenPrepare/AArch64/sink-free-instructions.ll
+++ b/llvm/test/Transforms/CodeGenPrepare/AArch64/sink-free-instructions.ll
@@ -1124,4 +1124,39 @@ if.else:
   ret <8 x i8> %b
 }
 
+define <8 x i8> @no_sink_bsl_not_after_splat_not_multiuse(<8 x i8> %m, <8 x i8> %b, i8 %s, i1 %c, ptr %p) {
+; CHECK-LABEL: @no_sink_bsl_not_after_splat_not_multiuse(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[N:%.*]] = xor <8 x i8> [[M:%.*]], splat (i8 -1)
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[NS:%.*]] = xor i8 [[S:%.*]], -1
+; CHECK-NEXT:    [[INS:%.*]] = insertelement <8 x i8> poison, i8 [[NS]], i64 0
+; CHECK-NEXT:    [[SPL:%.*]] = shufflevector <8 x i8> [[INS]], <8 x i8> poison, <8 x i32> zeroinitializer
+; CHECK-NEXT:    [[X:%.*]] = and <8 x i8> [[M]], [[B:%.*]]
+; CHECK-NEXT:    [[Y:%.*]] = and <8 x i8> [[SPL]], [[N]]
+; CHECK-NEXT:    [[R:%.*]] = or <8 x i8> [[X]], [[Y]]
+; CHECK-NEXT:    store <8 x i8> [[R]], ptr [[P:%.*]], align 8
+; CHECK-NEXT:    ret <8 x i8> [[R]]
+; CHECK:       if.else:
+; CHECK-NEXT:    ret <8 x i8> [[N]]
+;
+entry:
+  %n = xor <8 x i8> %m, splat (i8 -1)
+  br i1 %c, label %if.then, label %if.else
+
+if.then:
+  %ns = xor i8 %s, -1
+  %ins = insertelement <8 x i8> poison, i8 %ns, i64 0
+  %spl = shufflevector <8 x i8> %ins, <8 x i8> poison, <8 x i32> zeroinitializer
+  %x = and <8 x i8> %m, %b
+  %y = and <8 x i8> %spl, %n
+  %r = or <8 x i8> %x, %y
+  store <8 x i8> %r, ptr %p
+  ret <8 x i8> %r
+
+if.else:
+  ret <8 x i8> %n
+}
+
 !0 = !{i64 0, i64 128}

>From 6a2a8b173c6bb30452228e3de0e3d83b816cafe2 Mon Sep 17 00:00:00 2001
From: Valeriy Savchenko <vsavchenko at apple.com>
Date: Fri, 16 Oct 2026 14:40:25 +0100
Subject: [PATCH 2/2] [AArch64][TTI] Drop single-use requirement on the mask
 from BSL sinking

---
 .../Target/AArch64/AArch64TargetTransformInfo.cpp   |  6 +++---
 llvm/test/CodeGen/AArch64/aarch64-bit-gen.ll        | 13 ++++++-------
 .../AArch64/sink-free-instructions.ll               |  3 ++-
 3 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
index 1c70822130fc6..a557d612a0077 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
@@ -3332,9 +3332,9 @@ static std::optional<Instruction *> instCombineSVESDIV(InstCombiner &IC,
 static bool matchBSL(const Instruction *I, Instruction *&MainAnd,
                      Instruction *&OtherAnd, Value *&A, Value *&B) {
   Value *MaskValue;
-  if (!match(I, m_c_Or(m_OneUse(m_Instruction(OtherAnd)),
-                       m_OneUse(m_c_And(m_OneUse(m_Not(m_Value(MaskValue))),
-                                        m_Value(A))))))
+  if (!match(I,
+             m_c_Or(m_OneUse(m_Instruction(OtherAnd)),
+                    m_OneUse(m_c_And(m_Not(m_Value(MaskValue)), m_Value(A))))))
     return false;
 
   if (!match(OtherAnd, m_c_And(m_Specific(MaskValue), m_Value(B))))
diff --git a/llvm/test/CodeGen/AArch64/aarch64-bit-gen.ll b/llvm/test/CodeGen/AArch64/aarch64-bit-gen.ll
index 09ae5c2dc6590..01bb811051ed5 100644
--- a/llvm/test/CodeGen/AArch64/aarch64-bit-gen.ll
+++ b/llvm/test/CodeGen/AArch64/aarch64-bit-gen.ll
@@ -322,16 +322,15 @@ if.else:
 define <8 x i8> @test_bit_sink_not_after_splat_not_multiuse(<8 x i8> %m, <8 x i8> %b, i8 %s, i1 %c, ptr %p) {
 ; CHECK-SD-LABEL: test_bit_sink_not_after_splat_not_multiuse:
 ; CHECK-SD:       // %bb.0: // %entry
-; CHECK-SD-NEXT:    fmov d2, d0
-; CHECK-SD-NEXT:    mvn v0.8b, v0.8b
 ; CHECK-SD-NEXT:    tbz w1, #0, .LBB13_2
 ; CHECK-SD-NEXT:  // %bb.1: // %if.then
-; CHECK-SD-NEXT:    dup v3.8b, w0
-; CHECK-SD-NEXT:    and v1.8b, v2.8b, v1.8b
-; CHECK-SD-NEXT:    bic v0.8b, v0.8b, v3.8b
-; CHECK-SD-NEXT:    orr v0.8b, v1.8b, v0.8b
+; CHECK-SD-NEXT:    dup v2.8b, w0
+; CHECK-SD-NEXT:    mvn v2.8b, v2.8b
+; CHECK-SD-NEXT:    bsl v0.8b, v1.8b, v2.8b
 ; CHECK-SD-NEXT:    str d0, [x2]
-; CHECK-SD-NEXT:  .LBB13_2: // %common.ret
+; CHECK-SD-NEXT:    ret
+; CHECK-SD-NEXT:  .LBB13_2:
+; CHECK-SD-NEXT:    mvn v0.8b, v0.8b
 ; CHECK-SD-NEXT:    ret
 ;
 ; CHECK-GI-LABEL: test_bit_sink_not_after_splat_not_multiuse:
diff --git a/llvm/test/Transforms/CodeGenPrepare/AArch64/sink-free-instructions.ll b/llvm/test/Transforms/CodeGenPrepare/AArch64/sink-free-instructions.ll
index 680ac477383a0..132b093872973 100644
--- a/llvm/test/Transforms/CodeGenPrepare/AArch64/sink-free-instructions.ll
+++ b/llvm/test/Transforms/CodeGenPrepare/AArch64/sink-free-instructions.ll
@@ -1133,8 +1133,9 @@ define <8 x i8> @no_sink_bsl_not_after_splat_not_multiuse(<8 x i8> %m, <8 x i8>
 ; CHECK-NEXT:    [[NS:%.*]] = xor i8 [[S:%.*]], -1
 ; CHECK-NEXT:    [[INS:%.*]] = insertelement <8 x i8> poison, i8 [[NS]], i64 0
 ; CHECK-NEXT:    [[SPL:%.*]] = shufflevector <8 x i8> [[INS]], <8 x i8> poison, <8 x i32> zeroinitializer
+; CHECK-NEXT:    [[TMP0:%.*]] = xor <8 x i8> [[M]], splat (i8 -1)
 ; CHECK-NEXT:    [[X:%.*]] = and <8 x i8> [[M]], [[B:%.*]]
-; CHECK-NEXT:    [[Y:%.*]] = and <8 x i8> [[SPL]], [[N]]
+; CHECK-NEXT:    [[Y:%.*]] = and <8 x i8> [[SPL]], [[TMP0]]
 ; CHECK-NEXT:    [[R:%.*]] = or <8 x i8> [[X]], [[Y]]
 ; CHECK-NEXT:    store <8 x i8> [[R]], ptr [[P:%.*]], align 8
 ; CHECK-NEXT:    ret <8 x i8> [[R]]



More information about the llvm-branch-commits mailing list