summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
authorQingShan Zhang <qshanz@cn.ibm.com>2019-12-30 03:18:31 +0000
committerQingShan Zhang <qshanz@cn.ibm.com>2019-12-30 03:18:31 +0000
commit874a8004f93538a0c9b335a7e1e34d80b57ebccd (patch)
treefbb8f2abcc16f85bc4092691d58d04e592f96ba6 /llvm/lib/Target
parent266cd7717c8126213a7560d26da5495053be90c0 (diff)
downloadbcm5719-llvm-874a8004f93538a0c9b335a7e1e34d80b57ebccd.tar.gz
bcm5719-llvm-874a8004f93538a0c9b335a7e1e34d80b57ebccd.zip
[PowerPC] Exploit the rlwinm instructions for "and" with constant
For now, PowerPC will using several instructions to get the constant and "and" it with the following case: define i32 @test1(i32 %a) { %and = and i32 %a, -2 ret i32 %and } However, we could exploit it with the rotate mask instructions. MB ME +----------------------+ |xxxxxxxxxxx00011111000| +----------------------+ 0 32 64 Notice that, we can only do it if the MB is larger than 32 and MB <= ME as RLWINM will replace the content of [0 - 32) with [32 - 64) even we didn't rotate it. Differential Revision: https://reviews.llvm.org/D71829
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h24
-rw-r--r--llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp20
2 files changed, 44 insertions, 0 deletions
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
index 74b67bd2e92..49443679bb3 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
@@ -82,6 +82,30 @@ static inline bool isRunOfOnes(unsigned Val, unsigned &MB, unsigned &ME) {
return false;
}
+static inline bool isRunOfOnes64(uint64_t Val, unsigned &MB, unsigned &ME) {
+ if (!Val)
+ return false;
+
+ if (isShiftedMask_64(Val)) {
+ // look for the first non-zero bit
+ MB = countLeadingZeros(Val);
+ // look for the first zero bit after the run of ones
+ ME = countLeadingZeros((Val - 1) ^ Val);
+ return true;
+ } else {
+ Val = ~Val; // invert mask
+ if (isShiftedMask_64(Val)) {
+ // effectively look for the first zero bit
+ ME = countLeadingZeros(Val) - 1;
+ // effectively look for the first one bit after the run of zeros
+ MB = countLeadingZeros((Val - 1) ^ Val) + 1;
+ return true;
+ }
+ }
+ // no run present
+ return false;
+}
+
} // end namespace llvm
// Generated files will use "namespace PPC". To avoid symbol clash,
diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
index f1e9b159d3c..a1f9de62b05 100644
--- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
@@ -4456,6 +4456,26 @@ bool PPCDAGToDAGISel::tryAndWithMask(SDNode *N) {
CurDAG->SelectNodeTo(N, PPC::RLDICR, MVT::i64, Ops);
return true;
}
+
+ // It is not 16-bit imm that means we need two instructions at least if
+ // using "and" instruction. Try to exploit it with rotate mask instructions.
+ if (isRunOfOnes64(Imm64, MB, ME)) {
+ if (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 content of [0 - 32) with [32 - 64) even
+ // we didn't rotate it.
+ SDValue Ops[] = { Val, getI64Imm(0, dl), getI64Imm(MB - 32, dl),
+ getI64Imm(ME - 32, dl) };
+ CurDAG->SelectNodeTo(N, PPC::RLWINM8, MVT::i64, Ops);
+ return true;
+ }
+ // TODO - handle it with rldicl + rldicl
+ }
}
return false;
OpenPOWER on IntegriCloud