diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index a63cc8ad9ce8..39b472f20e81 100644 --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -912,84 +912,95 @@ class BitPermutationSelector { } }; - // Return true if something interesting was deduced, return false if we're + using ValueBitsMemoizedValue = std::pair>; + using ValueBitsMemoizer = + DenseMap>; + 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 &Bits) { + // uninteresting for instruction selection) through the SmallVector. + std::pair *> 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 &Bits = ValueEntry->second; + Bits.resize(NumBits); + switch (V.getOpcode()) { default: break; case ISD::ROTL: if (isa(V.getOperand(1))) { unsigned RotAmt = V.getConstantOperandVal(1); - SmallVector 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(V.getOperand(1))) { unsigned ShiftAmt = V.getConstantOperandVal(1); - SmallVector 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(V.getOperand(1))) { unsigned ShiftAmt = V.getConstantOperandVal(1); - SmallVector 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(V.getOperand(1))) { uint64_t Mask = V.getConstantOperandVal(1); - SmallVector 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 *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 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: ");