forked from OSchip/llvm-project
[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:
parent
6a91af7eb7
commit
dc698c3e91
|
@ -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: ");
|
||||
|
|
Loading…
Reference in New Issue