[PATCH] D127603: [AArch64] isSeveralBitsExtractOpFromShr - match UBFM patterns with value tracking (RFC)

Simon Pilgrim via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sun Jun 12 09:21:28 PDT 2022


RKSimon created this revision.
RKSimon added reviewers: dmgreen, efriedma.
Herald added subscribers: hiraditya, kristof.beyls.
Herald added a project: All.
RKSimon requested review of this revision.
Herald added a project: LLVM.

This came about while I was investigating the lost bit extractions on D125836 <https://reviews.llvm.org/D125836> - it didn't help but is a more general implementation than just matching AND masks.

With a bit more work I'm wondering how many of the 'isBitfieldExtractOp' patterns could actually be performed with just value tracking and SimplifyMultipleUseDemandedBits.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D127603

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


Index: llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
===================================================================
--- llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
+++ llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
@@ -1947,12 +1947,12 @@
   return true;
 }
 
-static bool isSeveralBitsExtractOpFromShr(SDNode *N, unsigned &Opc,
-                                          SDValue &Opd0, unsigned &LSB,
-                                          unsigned &MSB) {
+static bool isSeveralBitsExtractOpFromShr(SelectionDAG *CurDAG, SDNode *N,
+                                          unsigned &Opc, SDValue &Opd0,
+                                          unsigned &LSB, unsigned &MSB) {
   // We are looking for the following pattern which basically extracts several
   // continuous bits from the source value and places it from the LSB of the
-  // destination value, all other bits of the destination value or set to zero:
+  // destination value, all other bits of the destination value are set to zero:
   //
   // Value2 = AND Value, MaskImm
   // SRL Value2, ShiftImm
@@ -1964,36 +1964,42 @@
   // UBFM Value, ShiftImm, BitWide + SrlImm -1
   //
 
-  if (N->getOpcode() != ISD::SRL)
+  uint64_t SrlImm = 0;
+  if (N->getOpcode() != ISD::SRL || !isIntImmediate(N->getOperand(1), SrlImm))
     return false;
 
-  uint64_t AndMask = 0;
-  if (!isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::AND, AndMask))
+  // Determine the number of known active bits that are being shifted.
+  SDValue ShiftSrc = N->getOperand(0);
+  KnownBits Known = CurDAG->computeKnownBits(ShiftSrc);
+  unsigned NumBits = Known.getBitWidth();
+  unsigned MinLZ = Known.countMinLeadingZeros(); 
+  unsigned ActiveBits = NumBits - MinLZ;
+  if (ActiveBits <= SrlImm)
     return false;
 
-  Opd0 = N->getOperand(0).getOperand(0);
-
-  uint64_t SrlImm = 0;
-  if (!isIntImmediate(N->getOperand(1), SrlImm))
-    return false;
-
-  // Check whether we really have several bits extract here.
-  unsigned BitWide = 64 - countLeadingOnes(~(AndMask >> SrlImm));
-  if (BitWide && isMask_64(AndMask >> SrlImm)) {
+  // UBFM will implicitly zero-extend the result, so just based on the active
+  // bits we actually want to extract, see if we can peek through to an inner
+  // source and avoid the mask entirely.
+  const TargetLowering &TLI = CurDAG->getTargetLoweringInfo();
+  APInt DemandedBits = APInt::getBitsSet(NumBits, SrlImm, ActiveBits);
+  if (SDValue Src = TLI.SimplifyMultipleUseDemandedBits(ShiftSrc, DemandedBits,
+                                                        *CurDAG)) {
     if (N->getValueType(0) == MVT::i32)
       Opc = AArch64::UBFMWri;
     else
       Opc = AArch64::UBFMXri;
 
+    Opd0 = Src;
     LSB = SrlImm;
-    MSB = BitWide + SrlImm - 1;
+    MSB = ActiveBits - 1;
     return true;
   }
 
   return false;
 }
 
-static bool isBitfieldExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0,
+static bool isBitfieldExtractOpFromShr(SelectionDAG *CurDAG, SDNode *N,
+                                       unsigned &Opc, SDValue &Opd0,
                                        unsigned &Immr, unsigned &Imms,
                                        bool BiggerPattern) {
   assert((N->getOpcode() == ISD::SRA || N->getOpcode() == ISD::SRL) &&
@@ -2008,7 +2014,7 @@
          "Type checking must have been done before calling this function");
 
   // Check for AND + SRL doing several bits extract.
-  if (isSeveralBitsExtractOpFromShr(N, Opc, Opd0, Immr, Imms))
+  if (isSeveralBitsExtractOpFromShr(CurDAG, N, Opc, Opd0, Immr, Imms))
     return true;
 
   // We're looking for a shift of a shift.
@@ -2130,7 +2136,8 @@
                                       NumberOfIgnoredLowBits, BiggerPattern);
   case ISD::SRL:
   case ISD::SRA:
-    return isBitfieldExtractOpFromShr(N, Opc, Opd0, Immr, Imms, BiggerPattern);
+    return isBitfieldExtractOpFromShr(CurDAG, N, Opc, Opd0, Immr, Imms,
+                                      BiggerPattern);
 
   case ISD::SIGN_EXTEND_INREG:
     return isBitfieldExtractOpFromSExtInReg(N, Opc, Opd0, Immr, Imms);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D127603.436230.patch
Type: text/x-patch
Size: 4083 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220612/84bd10e0/attachment.bin>


More information about the llvm-commits mailing list