[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