diff options
| author | Stefan Pintilie <stefanp@ca.ibm.com> | 2023-09-06 21:25:28 -0400 |
|---|---|---|
| committer | Stefan Pintilie <stefanp@ca.ibm.com> | 2023-09-07 09:25:41 -0400 |
| commit | 492c1f3d7cf672a1ae4df85350daf05f82f558c6 (patch) | |
| tree | dec623d9fbab11c4b2139098c5c89fc527229aa0 /llvm/lib | |
| parent | 80225af4c1445c7818c6a71121d83bcc8ed7dd3b (diff) | |
| download | llvm-492c1f3d7cf672a1ae4df85350daf05f82f558c6.zip llvm-492c1f3d7cf672a1ae4df85350daf05f82f558c6.tar.gz llvm-492c1f3d7cf672a1ae4df85350daf05f82f558c6.tar.bz2 | |
[PowerPC] Merge rotate and clear into single instruction.
This patch tries to catch a codegen opportunity where the rotate and
mask can be merged into a single RLDCL instruction.
Reviewed By: lei, amyk
Differential Revision: https://reviews.llvm.org/D158328
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 98936fe..95a66442 100644 --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -424,6 +424,7 @@ private: bool tryFoldSWTestBRCC(SDNode *N); bool trySelectLoopCountIntrinsic(SDNode *N); bool tryAsSingleRLDICL(SDNode *N); + bool tryAsSingleRLDCL(SDNode *N); bool tryAsSingleRLDICR(SDNode *N); bool tryAsSingleRLWINM(SDNode *N); bool tryAsSingleRLWINM8(SDNode *N); @@ -5084,6 +5085,35 @@ bool PPCDAGToDAGISel::tryAsSingleRLWIMI(SDNode *N) { return false; } +bool PPCDAGToDAGISel::tryAsSingleRLDCL(SDNode *N) { + assert(N->getOpcode() == ISD::AND && "ISD::AND SDNode expected"); + + uint64_t Imm64; + if (!isInt64Immediate(N->getOperand(1).getNode(), Imm64) || !isMask_64(Imm64)) + return false; + + SDValue Val = N->getOperand(0); + + if (Val.getOpcode() != ISD::ROTL) + return false; + + // Looking to try to avoid a situation like this one: + // %2 = tail call i64 @llvm.fshl.i64(i64 %word, i64 %word, i64 23) + // %and1 = and i64 %2, 9223372036854775807 + // In this function we are looking to try to match RLDCL. However, the above + // DAG would better match RLDICL instead which is not what we are looking + // for here. + SDValue RotateAmt = Val.getOperand(1); + if (RotateAmt.getOpcode() == ISD::Constant) + return false; + + unsigned MB = 64 - llvm::countr_one(Imm64); + SDLoc dl(N); + SDValue Ops[] = {Val.getOperand(0), RotateAmt, getI32Imm(MB, dl)}; + CurDAG->SelectNodeTo(N, PPC::RLDCL, MVT::i64, Ops); + return true; +} + bool PPCDAGToDAGISel::tryAsSingleRLDICL(SDNode *N) { assert(N->getOpcode() == ISD::AND && "ISD::AND SDNode expected"); uint64_t Imm64; @@ -5604,8 +5634,9 @@ void PPCDAGToDAGISel::Select(SDNode *N) { case ISD::AND: // If this is an 'and' with a mask, try to emit rlwinm/rldicl/rldicr - if (tryAsSingleRLWINM(N) || tryAsSingleRLWIMI(N) || tryAsSingleRLDICL(N) || - tryAsSingleRLDICR(N) || tryAsSingleRLWINM8(N) || tryAsPairOfRLDICL(N)) + if (tryAsSingleRLWINM(N) || tryAsSingleRLWIMI(N) || tryAsSingleRLDCL(N) || + tryAsSingleRLDICL(N) || tryAsSingleRLDICR(N) || tryAsSingleRLWINM8(N) || + tryAsPairOfRLDICL(N)) return; // Other cases are autogenerated. |
