[PPC] Memoize getValueBits. NFC.

Summary: It triggers exponential behavior when the DAG has many branches.

Reviewers: hfinkel, kbarton

Subscribers: iteratee, nemanjai, echristo

Differential Revision: https://reviews.llvm.org/D23428

llvm-svn: 278548
This commit is contained in:
Tim Shen 2016-08-12 18:40:04 +00:00
parent 6a91af7eb7
commit dc698c3e91
1 changed files with 50 additions and 36 deletions

View File

@ -912,84 +912,95 @@ class BitPermutationSelector {
}
};
// Return true if something interesting was deduced, return false if we're
using ValueBitsMemoizedValue = std::pair<bool, SmallVector<ValueBit, 64>>;
using ValueBitsMemoizer =
DenseMap<SDValue, std::unique_ptr<ValueBitsMemoizedValue>>;
ValueBitsMemoizer Memoizer;
// Return a pair of bool and a SmallVector pointer to a memoization entry.
// The bool is true if something interesting was deduced, otherwise if we're
// providing only a generic representation of V (or something else likewise
// uninteresting for instruction selection).
bool getValueBits(SDValue V, SmallVector<ValueBit, 64> &Bits) {
// uninteresting for instruction selection) through the SmallVector.
std::pair<bool, SmallVector<ValueBit, 64> *> getValueBits(SDValue V,
unsigned NumBits) {
auto &ValueEntry = Memoizer[V];
if (ValueEntry)
return std::make_pair(ValueEntry->first, &ValueEntry->second);
ValueEntry.reset(new ValueBitsMemoizedValue());
bool &Interesting = ValueEntry->first;
SmallVector<ValueBit, 64> &Bits = ValueEntry->second;
Bits.resize(NumBits);
switch (V.getOpcode()) {
default: break;
case ISD::ROTL:
if (isa<ConstantSDNode>(V.getOperand(1))) {
unsigned RotAmt = V.getConstantOperandVal(1);
SmallVector<ValueBit, 64> LHSBits(Bits.size());
getValueBits(V.getOperand(0), LHSBits);
const auto &LHSBits = *getValueBits(V.getOperand(0), NumBits).second;
for (unsigned i = 0; i < Bits.size(); ++i)
Bits[i] = LHSBits[i < RotAmt ? i + (Bits.size() - RotAmt) : i - RotAmt];
for (unsigned i = 0; i < NumBits; ++i)
Bits[i] = LHSBits[i < RotAmt ? i + (NumBits - RotAmt) : i - RotAmt];
return true;
return std::make_pair(Interesting = true, &Bits);
}
break;
case ISD::SHL:
if (isa<ConstantSDNode>(V.getOperand(1))) {
unsigned ShiftAmt = V.getConstantOperandVal(1);
SmallVector<ValueBit, 64> LHSBits(Bits.size());
getValueBits(V.getOperand(0), LHSBits);
const auto &LHSBits = *getValueBits(V.getOperand(0), NumBits).second;
for (unsigned i = ShiftAmt; i < Bits.size(); ++i)
for (unsigned i = ShiftAmt; i < NumBits; ++i)
Bits[i] = LHSBits[i - ShiftAmt];
for (unsigned i = 0; i < ShiftAmt; ++i)
Bits[i] = ValueBit(ValueBit::ConstZero);
return true;
return std::make_pair(Interesting = true, &Bits);
}
break;
case ISD::SRL:
if (isa<ConstantSDNode>(V.getOperand(1))) {
unsigned ShiftAmt = V.getConstantOperandVal(1);
SmallVector<ValueBit, 64> LHSBits(Bits.size());
getValueBits(V.getOperand(0), LHSBits);
const auto &LHSBits = *getValueBits(V.getOperand(0), NumBits).second;
for (unsigned i = 0; i < Bits.size() - ShiftAmt; ++i)
for (unsigned i = 0; i < NumBits - ShiftAmt; ++i)
Bits[i] = LHSBits[i + ShiftAmt];
for (unsigned i = Bits.size() - ShiftAmt; i < Bits.size(); ++i)
for (unsigned i = NumBits - ShiftAmt; i < NumBits; ++i)
Bits[i] = ValueBit(ValueBit::ConstZero);
return true;
return std::make_pair(Interesting = true, &Bits);
}
break;
case ISD::AND:
if (isa<ConstantSDNode>(V.getOperand(1))) {
uint64_t Mask = V.getConstantOperandVal(1);
SmallVector<ValueBit, 64> LHSBits(Bits.size());
bool LHSTrivial = getValueBits(V.getOperand(0), LHSBits);
for (unsigned i = 0; i < Bits.size(); ++i)
if (((Mask >> i) & 1) == 1)
Bits[i] = LHSBits[i];
else
Bits[i] = ValueBit(ValueBit::ConstZero);
const SmallVector<ValueBit, 64> *LHSBits;
// Mark this as interesting, only if the LHS was also interesting. This
// prevents the overall procedure from matching a single immediate 'and'
// (which is non-optimal because such an and might be folded with other
// things if we don't select it here).
return LHSTrivial;
std::tie(Interesting, LHSBits) = getValueBits(V.getOperand(0), NumBits);
for (unsigned i = 0; i < NumBits; ++i)
if (((Mask >> i) & 1) == 1)
Bits[i] = (*LHSBits)[i];
else
Bits[i] = ValueBit(ValueBit::ConstZero);
return std::make_pair(Interesting, &Bits);
}
break;
case ISD::OR: {
SmallVector<ValueBit, 64> LHSBits(Bits.size()), RHSBits(Bits.size());
getValueBits(V.getOperand(0), LHSBits);
getValueBits(V.getOperand(1), RHSBits);
const auto &LHSBits = *getValueBits(V.getOperand(0), NumBits).second;
const auto &RHSBits = *getValueBits(V.getOperand(1), NumBits).second;
bool AllDisjoint = true;
for (unsigned i = 0; i < Bits.size(); ++i)
for (unsigned i = 0; i < NumBits; ++i)
if (LHSBits[i].isZero())
Bits[i] = RHSBits[i];
else if (RHSBits[i].isZero())
@ -1002,14 +1013,14 @@ class BitPermutationSelector {
if (!AllDisjoint)
break;
return true;
return std::make_pair(Interesting = true, &Bits);
}
}
for (unsigned i = 0; i < Bits.size(); ++i)
for (unsigned i = 0; i < NumBits; ++i)
Bits[i] = ValueBit(V, i);
return false;
return std::make_pair(Interesting = false, &Bits);
}
// For each value (except the constant ones), compute the left-rotate amount
@ -1909,9 +1920,12 @@ public:
// rotate-and-shift/shift/and/or instructions, using a set of heuristics
// known to produce optimial code for common cases (like i32 byte swapping).
SDNode *Select(SDNode *N) {
Bits.resize(N->getValueType(0).getSizeInBits());
if (!getValueBits(SDValue(N, 0), Bits))
Memoizer.clear();
auto Result =
getValueBits(SDValue(N, 0), N->getValueType(0).getSizeInBits());
if (!Result.first)
return nullptr;
Bits = std::move(*Result.second);
DEBUG(dbgs() << "Considering bit-permutation-based instruction"
" selection for: ");