summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
diff options
context:
space:
mode:
authorHal Finkel <hfinkel@anl.gov>2015-01-04 15:43:55 +0000
committerHal Finkel <hfinkel@anl.gov>2015-01-04 15:43:55 +0000
commit241ba79f954f7546b087a16fd9522b0872d4b9cb (patch)
treed74a41f2564273479060332cbea994da3acbfb31 /llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
parent7c91552cd927fd998266cfcce21a37cc4dcfab91 (diff)
downloadbcm5719-llvm-241ba79f954f7546b087a16fd9522b0872d4b9cb.tar.gz
bcm5719-llvm-241ba79f954f7546b087a16fd9522b0872d4b9cb.zip
[PowerPC] Materialize i64 constants using rotation
Materializing full 64-bit constants on PPC64 can be expensive, requiring up to 5 instructions depending on the locations of the non-zero bits. Sometimes materializing a rotated constant, and then applying the inverse rotation, requires fewer instructions than the direct method. If so, do that instead. In r225132, I added support for forming constants using bit inversion. In effect, this reverts that commit and replaces it with rotation support. The bit inversion is useful for turning constants that are mostly ones into ones that are mostly zeros (thus enabling a more-efficient shift-based materialization), but the same effect can be obtained by using negative constants and a rotate, and that is at least as efficient, if not more. llvm-svn: 225135
Diffstat (limited to 'llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp')
-rw-r--r--llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp47
1 files changed, 29 insertions, 18 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
index 2e1c1abf5b6..868659421c7 100644
--- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
@@ -602,16 +602,19 @@ static unsigned SelectInt64CountDirect(int64_t Imm) {
return Result;
}
+static uint64_t Rot64(uint64_t Imm, unsigned R) {
+ return (Imm << R) | (Imm >> (64 - R));
+}
+
static unsigned SelectInt64Count(int64_t Imm) {
- unsigned DirectCount = SelectInt64CountDirect(Imm);
+ unsigned Count = SelectInt64CountDirect(Imm);
- // If might be cheaper to materialize the bit-inverted constant, and then
- // flip the bits (which takes one nor instruction).
- unsigned NotDirectCount = SelectInt64CountDirect(~(uint64_t) Imm) + 1;
- if (NotDirectCount < DirectCount)
- return NotDirectCount;
+ for (unsigned r = 1; r < 63; ++r) {
+ unsigned RCount = SelectInt64CountDirect(Rot64(Imm, r)) + 1;
+ Count = std::min(Count, RCount);
+ }
- return DirectCount;
+ return Count;
}
// Select a 64-bit constant. For cost-modeling purposes, SelectInt64Count
@@ -691,19 +694,27 @@ static SDNode *SelectInt64Direct(SelectionDAG *CurDAG, SDLoc dl, int64_t Imm) {
}
static SDNode *SelectInt64(SelectionDAG *CurDAG, SDLoc dl, int64_t Imm) {
- unsigned DirectCount = SelectInt64CountDirect(Imm);
-
- // If might be cheaper to materialize the bit-inverted constant, and then
- // flip the bits (which takes one nor instruction).
- unsigned NotDirectCount = SelectInt64CountDirect(~(uint64_t) Imm) + 1;
- if (NotDirectCount < DirectCount) {
- SDValue NotDirectVal =
- SDValue(SelectInt64Direct(CurDAG, dl, ~(uint64_t) Imm), 0);
- return CurDAG->getMachineNode(PPC::NOR8, dl, MVT::i64, NotDirectVal,
- NotDirectVal);
+ unsigned Count = SelectInt64CountDirect(Imm);
+ unsigned RMin = 0;
+
+ for (unsigned r = 1; r < 63; ++r) {
+ unsigned RCount = SelectInt64CountDirect(Rot64(Imm, r)) + 1;
+ if (RCount < Count) {
+ Count = RCount;
+ RMin = r;
+ }
}
- return SelectInt64Direct(CurDAG, dl, Imm);
+ if (!RMin)
+ return SelectInt64Direct(CurDAG, dl, Imm);
+
+ auto getI32Imm = [CurDAG](unsigned Imm) {
+ return CurDAG->getTargetConstant(Imm, MVT::i32);
+ };
+
+ SDValue Val = SDValue(SelectInt64Direct(CurDAG, dl, Rot64(Imm, RMin)), 0);
+ return CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, Val,
+ getI32Imm(64 - RMin), getI32Imm(0));
}
// Select a 64-bit constant.
OpenPOWER on IntegriCloud