[PowerPC] Follow-up to r318436 to get the missed CSE opportunities
The last of the three patches that https://reviews.llvm.org/D40348 was
broken up into.
Canonicalize the materialization of constants so that they are more likely
to be CSE'd regardless of the bit-width of the use. If a constant can be
materialized using PPC::LI, materialize it the same way always.
For example:
li 4, -1
li 4, 255
li 4, 65535
are equivalent if the uses only use the low byte. Canonicalize it to the
first form.
Differential Revision: https://reviews.llvm.org/D40348
llvm-svn: 320473
diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
index 2fff50b..a9ef10b 100644
--- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
@@ -786,8 +786,10 @@
// Simple value.
if (isInt<16>(Imm)) {
+ uint64_t SextImm = SignExtend64(Lo, 16);
+ SDValue SDImm = CurDAG->getTargetConstant(SextImm, dl, MVT::i64);
// Just the Lo bits.
- Result = CurDAG->getMachineNode(PPC::LI8, dl, MVT::i64, getI32Imm(Lo));
+ Result = CurDAG->getMachineNode(PPC::LI8, dl, MVT::i64, SDImm);
} else if (Lo) {
// Handle the Hi bits.
unsigned OpC = Hi ? PPC::LIS8 : PPC::LI8;
@@ -892,12 +894,74 @@
getI32Imm(64 - RMin), getI32Imm(MaskEnd));
}
+static unsigned allUsesTruncate(SelectionDAG *CurDAG, SDNode *N) {
+ unsigned MaxTruncation = 0;
+ // Cannot use range-based for loop here as we need the actual use (i.e. we
+ // need the operand number corresponding to the use). A range-based for
+ // will unbox the use and provide an SDNode*.
+ for (SDNode::use_iterator Use = N->use_begin(), UseEnd = N->use_end();
+ Use != UseEnd; ++Use) {
+ unsigned Opc =
+ Use->isMachineOpcode() ? Use->getMachineOpcode() : Use->getOpcode();
+ switch (Opc) {
+ default: return 0;
+ case ISD::TRUNCATE:
+ if (Use->isMachineOpcode())
+ return 0;
+ MaxTruncation =
+ std::max(MaxTruncation, Use->getValueType(0).getSizeInBits());
+ continue;
+ case ISD::STORE: {
+ if (Use->isMachineOpcode())
+ return 0;
+ StoreSDNode *STN = cast<StoreSDNode>(*Use);
+ unsigned MemVTSize = STN->getMemoryVT().getSizeInBits();
+ if (MemVTSize == 64 || Use.getOperandNo() != 0)
+ return 0;
+ MaxTruncation = std::max(MaxTruncation, MemVTSize);
+ continue;
+ }
+ case PPC::STW8:
+ case PPC::STWX8:
+ case PPC::STWU8:
+ case PPC::STWUX8:
+ if (Use.getOperandNo() != 0)
+ return 0;
+ MaxTruncation = std::max(MaxTruncation, 32u);
+ continue;
+ case PPC::STH8:
+ case PPC::STHX8:
+ case PPC::STHU8:
+ case PPC::STHUX8:
+ if (Use.getOperandNo() != 0)
+ return 0;
+ MaxTruncation = std::max(MaxTruncation, 16u);
+ continue;
+ case PPC::STB8:
+ case PPC::STBX8:
+ case PPC::STBU8:
+ case PPC::STBUX8:
+ if (Use.getOperandNo() != 0)
+ return 0;
+ MaxTruncation = std::max(MaxTruncation, 8u);
+ continue;
+ }
+ }
+ return MaxTruncation;
+}
+
// Select a 64-bit constant.
static SDNode *selectI64Imm(SelectionDAG *CurDAG, SDNode *N) {
SDLoc dl(N);
// Get 64 bit value.
int64_t Imm = cast<ConstantSDNode>(N)->getZExtValue();
+ if (unsigned MinSize = allUsesTruncate(CurDAG, N)) {
+ uint64_t SextImm = SignExtend64(Imm, MinSize);
+ SDValue SDImm = CurDAG->getTargetConstant(SextImm, dl, MVT::i64);
+ if (isInt<16>(SextImm))
+ return CurDAG->getMachineNode(PPC::LI8, dl, MVT::i64, SDImm);
+ }
return selectI64Imm(CurDAG, dl, Imm);
}