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

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Oct 16 07:59:16 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-aarch64

Author: Valeriy Savchenko (SavchenkoValeriy)

<details>
<summary>Changes</summary>

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>

---
Full diff: https://github.com/llvm/llvm-project/pull/232786.diff


3 Files Affected:

- (modified) llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp (+3-3) 
- (modified) llvm/test/CodeGen/AArch64/aarch64-bit-gen.ll (+44) 
- (modified) llvm/test/Transforms/CodeGenPrepare/AArch64/sink-free-instructions.ll (+36) 


``````````diff
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 0dcd4bb159460..01bb811051ed5 100644
--- a/llvm/test/CodeGen/AArch64/aarch64-bit-gen.ll
+++ b/llvm/test/CodeGen/AArch64/aarch64-bit-gen.ll
@@ -318,3 +318,47 @@ 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:    tbz w1, #0, .LBB13_2
+; CHECK-SD-NEXT:  // %bb.1: // %if.then
+; 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:    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:
+; 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..132b093872973 100644
--- a/llvm/test/Transforms/CodeGenPrepare/AArch64/sink-free-instructions.ll
+++ b/llvm/test/Transforms/CodeGenPrepare/AArch64/sink-free-instructions.ll
@@ -1124,4 +1124,40 @@ 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:    [[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]], [[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]]
+; 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}

``````````

</details>


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


More information about the llvm-branch-commits mailing list