aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib
diff options
context:
space:
mode:
authorStefan Pintilie <stefanp@ca.ibm.com>2023-09-06 21:25:28 -0400
committerStefan Pintilie <stefanp@ca.ibm.com>2023-09-07 09:25:41 -0400
commit492c1f3d7cf672a1ae4df85350daf05f82f558c6 (patch)
treedec623d9fbab11c4b2139098c5c89fc527229aa0 /llvm/lib
parent80225af4c1445c7818c6a71121d83bcc8ed7dd3b (diff)
downloadllvm-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.cpp35
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.