[PATCH] D147266: [AArch64] Add IR intrinsics for vbsl* C intrinsics

Pranav Kant via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed May 10 15:06:29 PDT 2023


pranavk updated this revision to Diff 521115.
pranavk added a comment.

[AArch64] Change shouldSinkOperand to allow bitselect instructions


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D147266/new/

https://reviews.llvm.org/D147266

Files:
  llvm/lib/Target/AArch64/AArch64ISelLowering.cpp


Index: llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
===================================================================
--- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -14332,6 +14332,61 @@
 
     return true;
   }
+  case Instruction::And: {
+    // If Or(And(A, maskValue), And(B, ~maskValue)), sink ~maskValue
+    // where ~maskValue = xor maskValue, -1
+    // This is to select more performant bitselect instruction with NEON.
+
+    // We start checking for this code sequence from AND instruction containing
+    // ~maskValue because operands are sunk just before the Instruction* I
+    // passed to this function. Starting pattern matching with any other
+    // instruction (such as Or) would lead to malformed IR
+
+    // Check if this AND instruction is part of bigger tree rooted at Or.
+    if (Subtarget->hasNEON() && I->getNumUses() == 1) {
+      Use &U = *(I->use_begin());
+      Instruction *OI = cast<Instruction>(U.getUser());
+      Value *And0_Op0 = nullptr, *And0_Op1 = nullptr, *And1_Op0 = nullptr,
+            *And1_Op1 = nullptr;
+      if (!OI ||
+          !match(OI, m_Or(m_And(m_Value(And0_Op0), m_Value(And0_Op1)),
+                          m_And(m_Value(And1_Op0), m_Value(And1_Op1)))) ||
+          !all_of(OI->operands(), [](Value *V) { return V->hasOneUser(); }))
+        return false;
+
+      ArrayRef<ArrayRef<Value *>> Ands = {{And0_Op0, And0_Op1},
+                                          {And1_Op0, And1_Op1}};
+      for (unsigned AndIndex = 0; AndIndex < Ands.size(); ++AndIndex) {
+        const unsigned OtherAndIndex = (AndIndex + 1) % 2;
+
+        // Iterate operands of selected And
+        for (unsigned AndOpIndex = 0; AndOpIndex < 2; ++AndOpIndex) {
+          if (const Instruction *XI =
+                  dyn_cast<Instruction>(Ands[AndIndex][AndOpIndex]);
+              XI && XI->getOpcode() == Instruction::Xor) {
+            Constant *MaskConst;
+            Value *MaskValue;
+            if (!match(XI, m_Xor(m_Value(MaskValue), m_Constant(MaskConst))) &&
+                !match(XI, m_Xor(m_Constant(MaskConst), m_Value(MaskValue))))
+              return false;
+
+            if (!MaskConst->isAllOnesValue())
+              return false;
+
+            // one of the operands of other AND should be MaskValue
+            if (!any_of(Ands[OtherAndIndex],
+                        [&MaskValue](Value *V) { return V == MaskValue; }))
+              return false;
+
+            auto TI = cast<Instruction>(OI->getOperand(AndIndex));
+            Ops.push_back(&TI->getOperandUse(AndOpIndex));
+            return true;
+          }
+        }
+      }
+    }
+    return false;
+  }
   case Instruction::Mul: {
     int NumZExts = 0, NumSExts = 0;
     for (auto &Op : I->operands()) {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D147266.521115.patch
Type: text/x-patch
Size: 2822 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20230510/e9bae05b/attachment.bin>


More information about the cfe-commits mailing list