[PATCH] D93894: [PowerPC] Expand BitPermutation to handle cases of the single immediate 'and'.

Qiu Chaofan via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 22 01:04:21 PST 2021


qiucf added inline comments.


================
Comment at: llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp:1700
+  // This method checks if it's optimal to select the single `and` with
+  // bit-permutation-based stratege. Considering the cases where `and` can be
+  // folded with its LHS, determine which stratege use less instruction. Return
----------------
`stratege` -> `strategy`?


================
Comment at: llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp:1714
+        // Compare which kind of conversion is better.
+        if ((NumBitPermInsts + /* xor */ 1) > (NumSelectInsts + /* andc */ 1))
+          return false;
----------------
Although it's nit, I believe it's better to remove `+1` on both sides, and simply comment here that `andc` is needed for `NumSelect` case.


================
Comment at: llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp:2119
+    // RLDICL + RLDICR
+    else if (BG2.EndIdx == 63) {
+      SDValue Ops1[] = {ExtendToInt64(BG1.V, dl),
----------------
Use `if` instead of `else if`? since each conditional block in this function always returns.


================
Comment at: llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp:4517
 
-bool PPCDAGToDAGISel::tryAsSingleRLWINM(SDNode *N) {
-  assert(N->getOpcode() == ISD::AND && "ISD::AND SDNode expected");
-  unsigned Imm;
-  if (!isInt32Immediate(N->getOperand(1), Imm))
-    return false;
-
-  SDLoc dl(N);
-  SDValue Val = N->getOperand(0);
-  unsigned SH, MB, ME;
-  // If this is an and of a value rotated between 0 and 31 bits and then and'd
-  // with a mask, emit rlwinm
-  if (isRotateAndMask(Val.getNode(), Imm, false, SH, MB, ME)) {
-    Val = Val.getOperand(0);
-    SDValue Ops[] = {Val, getI32Imm(SH, dl), getI32Imm(MB, dl),
-                     getI32Imm(ME, dl)};
-    CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops);
-    return true;
-  }
-
-  // If this is just a masked value where the input is not handled, and
-  // is not a rotate-left (handled by a pattern in the .td file), emit rlwinm
-  if (isRunOfOnes(Imm, MB, ME) && Val.getOpcode() != ISD::ROTL) {
-    SDValue Ops[] = {Val, getI32Imm(0, dl), getI32Imm(MB, dl),
-                     getI32Imm(ME, dl)};
-    CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops);
-    return true;
-  }
-
-  // AND X, 0 -> 0, not "rlwinm 32".
-  if (Imm == 0) {
-    ReplaceUses(SDValue(N, 0), N->getOperand(1));
-    return true;
-  }
-
-  return false;
-}
-
-bool PPCDAGToDAGISel::tryAsSingleRLWINM8(SDNode *N) {
-  assert(N->getOpcode() == ISD::AND && "ISD::AND SDNode expected");
-  uint64_t Imm64;
-  if (!isInt64Immediate(N->getOperand(1).getNode(), Imm64))
-    return false;
-
-  unsigned MB, ME;
-  if (isRunOfOnes64(Imm64, MB, ME) && MB >= 32 && MB <= ME) {
-    //                MB  ME
-    // +----------------------+
-    // |xxxxxxxxxxx00011111000|
-    // +----------------------+
-    //  0         32         64
-    // We can only do it if the MB is larger than 32 and MB <= ME
-    // as RLWINM will replace the contents of [0 - 32) with [32 - 64) even
-    // we didn't rotate it.
-    SDLoc dl(N);
-    SDValue Ops[] = {N->getOperand(0), getI64Imm(0, dl), getI64Imm(MB - 32, dl),
-                     getI64Imm(ME - 32, dl)};
-    CurDAG->SelectNodeTo(N, PPC::RLWINM8, MVT::i64, Ops);
-    return true;
-  }
-
-  return false;
-}
-
-bool PPCDAGToDAGISel::tryAsPairOfRLDICL(SDNode *N) {
-  assert(N->getOpcode() == ISD::AND && "ISD::AND SDNode expected");
-  uint64_t Imm64;
-  if (!isInt64Immediate(N->getOperand(1).getNode(), Imm64))
-    return false;
-
-  // Do nothing if it is 16-bit imm as the pattern in the .td file handle
-  // it well with "andi.".
-  if (isUInt<16>(Imm64))
-    return false;
-
-  SDLoc Loc(N);
-  SDValue Val = N->getOperand(0);
-
-  // Optimized with two rldicl's as follows:
-  // Add missing bits on left to the mask and check that the mask is a
-  // wrapped run of ones, i.e.
-  // Change pattern |0001111100000011111111|
-  //             to |1111111100000011111111|.
-  unsigned NumOfLeadingZeros = countLeadingZeros(Imm64);
-  if (NumOfLeadingZeros != 0)
-    Imm64 |= maskLeadingOnes<uint64_t>(NumOfLeadingZeros);
-
-  unsigned MB, ME;
-  if (!isRunOfOnes64(Imm64, MB, ME))
-    return false;
-
-  //         ME     MB                   MB-ME+63
-  // +----------------------+     +----------------------+
-  // |1111111100000011111111| ->  |0000001111111111111111|
-  // +----------------------+     +----------------------+
-  //  0                    63      0                    63
-  // There are ME + 1 ones on the left and (MB - ME + 63) & 63 zeros in between.
-  unsigned OnesOnLeft = ME + 1;
-  unsigned ZerosInBetween = (MB - ME + 63) & 63;
-  // Rotate left by OnesOnLeft (so leading ones are now trailing ones) and clear
-  // on the left the bits that are already zeros in the mask.
-  Val = SDValue(CurDAG->getMachineNode(PPC::RLDICL, Loc, MVT::i64, Val,
-                                       getI64Imm(OnesOnLeft, Loc),
-                                       getI64Imm(ZerosInBetween, Loc)),
-                0);
-  //        MB-ME+63                      ME     MB
-  // +----------------------+     +----------------------+
-  // |0000001111111111111111| ->  |0001111100000011111111|
-  // +----------------------+     +----------------------+
-  //  0                    63      0                    63
-  // Rotate back by 64 - OnesOnLeft to undo previous rotate. Then clear on the
-  // left the number of ones we previously added.
-  SDValue Ops[] = {Val, getI64Imm(64 - OnesOnLeft, Loc),
-                   getI64Imm(NumOfLeadingZeros, Loc)};
-  CurDAG->SelectNodeTo(N, PPC::RLDICL, MVT::i64, Ops);
-  return true;
-}
-
-bool PPCDAGToDAGISel::tryAsSingleRLWIMI(SDNode *N) {
-  assert(N->getOpcode() == ISD::AND && "ISD::AND SDNode expected");
-  unsigned Imm;
-  if (!isInt32Immediate(N->getOperand(1), Imm))
-    return false;
-
-  SDValue Val = N->getOperand(0);
-  unsigned Imm2;
-  // ISD::OR doesn't get all the bitfield insertion fun.
-  // (and (or x, c1), c2) where isRunOfOnes(~(c1^c2)) might be a
-  // bitfield insert.
-  if (Val.getOpcode() != ISD::OR || !isInt32Immediate(Val.getOperand(1), Imm2))
-    return false;
-
-  // The idea here is to check whether this is equivalent to:
-  //   (c1 & m) | (x & ~m)
-  // where m is a run-of-ones mask. The logic here is that, for each bit in
-  // c1 and c2:
-  //  - if both are 1, then the output will be 1.
-  //  - if both are 0, then the output will be 0.
-  //  - if the bit in c1 is 0, and the bit in c2 is 1, then the output will
-  //    come from x.
-  //  - if the bit in c1 is 1, and the bit in c2 is 0, then the output will
-  //    be 0.
-  //  If that last condition is never the case, then we can form m from the
-  //  bits that are the same between c1 and c2.
-  unsigned MB, ME;
-  if (isRunOfOnes(~(Imm ^ Imm2), MB, ME) && !(~Imm & Imm2)) {
-    SDLoc dl(N);
-    SDValue Ops[] = {Val.getOperand(0), Val.getOperand(1), getI32Imm(0, dl),
-                     getI32Imm(MB, dl), getI32Imm(ME, dl)};
-    ReplaceNode(N, CurDAG->getMachineNode(PPC::RLWIMI, dl, MVT::i32, Ops));
-    return true;
-  }
-
-  return false;
-}
-
 bool PPCDAGToDAGISel::tryAsSingleRLDICL(SDNode *N) {
   assert(N->getOpcode() == ISD::AND && "ISD::AND SDNode expected");
----------------
This case "can't be handled by BitPerm" && "can't be handled by TableGen"?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D93894



More information about the llvm-commits mailing list