Unverified Commit 687bbf85 authored by Roman Lebedev's avatar Roman Lebedev
Browse files

[llvm-exegesis] CombinationGenerator: don't store function_ref

function_ref is non-owning, so if we get it as a parameter in constructor,
our reference goes out-of-scope as soon as constructor returns.
Instead, let's just take it as a parameter to the actual `generate()` call
parent e26c24b8
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -156,9 +156,9 @@ class CombinationGenerator {
  };

  const ArrayRef<choices_storage_type> VariablesChoices;
  const function_ref<bool(ArrayRef<choice_type>)> &Callback;

  void performGeneration() const {
  void performGeneration(
      const function_ref<bool(ArrayRef<choice_type>)> Callback) const {
    SmallVector<WrappingIterator<choice_type>, variable_smallsize>
        VariablesState;

@@ -200,9 +200,8 @@ class CombinationGenerator {
  };

public:
  CombinationGenerator(ArrayRef<choices_storage_type> VariablesChoices_,
                       const function_ref<bool(ArrayRef<choice_type>)> &Cb_)
      : VariablesChoices(VariablesChoices_), Callback(Cb_) {
  CombinationGenerator(ArrayRef<choices_storage_type> VariablesChoices_)
      : VariablesChoices(VariablesChoices_) {
#ifndef NDEBUG
    assert(!VariablesChoices.empty() && "There should be some variables.");
    llvm::for_each(VariablesChoices, [](ArrayRef<choice_type> VariableChoices) {
@@ -225,7 +224,9 @@ public:

  // Actually perform exhaustive combination generation.
  // Each result will be passed into the callback.
  void generate() { performGeneration(); }
  void generate(const function_ref<bool(ArrayRef<choice_type>)> Callback) {
    performGeneration(Callback);
  }
};

} // namespace exegesis
+7 −7
Original line number Diff line number Diff line
@@ -784,18 +784,18 @@ std::vector<InstructionTemplate> ExegesisX86Target::generateInstructionVariants(
  std::vector<InstructionTemplate> Variants;
  size_t NumVariants;
  CombinationGenerator<MCOperand, decltype(VariableChoices)::value_type, 4> G(
      VariableChoices, [&](ArrayRef<MCOperand> State) -> bool {
        Variants.emplace_back(&Instr);
        Variants.back().setVariableValues(State);
        // Did we run out of space for variants?
        return Variants.size() >= NumVariants;
      });
      VariableChoices);

  // How many operand combinations can we produce, within the limit?
  NumVariants = std::min(G.numCombinations(), (size_t)MaxConfigsPerOpcode);
  // And actually produce all the wanted operand combinations.
  Variants.reserve(NumVariants);
  G.generate();
  G.generate([&](ArrayRef<MCOperand> State) -> bool {
    Variants.emplace_back(&Instr);
    Variants.back().setVariableValues(State);
    // Did we run out of space for variants?
    return Variants.size() >= NumVariants;
  });

  assert(Variants.size() == NumVariants &&
         Variants.size() <= MaxConfigsPerOpcode &&
+40 −48
Original line number Diff line number Diff line
@@ -20,13 +20,12 @@ TEST(CombinationGenerator, Square) {
  const std::vector<std::vector<int>> Choices{{0, 1}, {2, 3}};

  std::vector<std::vector<int>> Variants;
  CombinationGenerator<int, std::vector<int>, 4> G(
      Choices, [&](ArrayRef<int> State) -> bool {
  CombinationGenerator<int, std::vector<int>, 4> G(Choices);
  const size_t NumVariants = G.numCombinations();
  G.generate([&](ArrayRef<int> State) -> bool {
    Variants.emplace_back(State);
    return false; // keep going
  });
  const size_t NumVariants = G.numCombinations();
  G.generate();

  const std::vector<std::vector<int>> ExpectedVariants{
      {0, 2},
@@ -42,13 +41,12 @@ TEST(CombinationGenerator, MiddleColumn) {
  const std::vector<std::vector<int>> Choices{{0}, {1, 2}, {3}};

  std::vector<std::vector<int>> Variants;
  CombinationGenerator<int, std::vector<int>, 4> G(
      Choices, [&](ArrayRef<int> State) -> bool {
  CombinationGenerator<int, std::vector<int>, 4> G(Choices);
  const size_t NumVariants = G.numCombinations();
  G.generate([&](ArrayRef<int> State) -> bool {
    Variants.emplace_back(State);
    return false; // keep going
  });
  const size_t NumVariants = G.numCombinations();
  G.generate();

  const std::vector<std::vector<int>> ExpectedVariants{
      {0, 1, 3},
@@ -62,13 +60,12 @@ TEST(CombinationGenerator, SideColumns) {
  const std::vector<std::vector<int>> Choices{{0, 1}, {2}, {3, 4}};

  std::vector<std::vector<int>> Variants;
  CombinationGenerator<int, std::vector<int>, 4> G(
      Choices, [&](ArrayRef<int> State) -> bool {
  CombinationGenerator<int, std::vector<int>, 4> G(Choices);
  const size_t NumVariants = G.numCombinations();
  G.generate([&](ArrayRef<int> State) -> bool {
    Variants.emplace_back(State);
    return false; // keep going
  });
  const size_t NumVariants = G.numCombinations();
  G.generate();

  const std::vector<std::vector<int>> ExpectedVariants{
      {0, 2, 3},
@@ -84,13 +81,12 @@ TEST(CombinationGenerator, LeftColumn) {
  const std::vector<std::vector<int>> Choices{{0, 1}, {2}};

  std::vector<std::vector<int>> Variants;
  CombinationGenerator<int, std::vector<int>, 4> G(
      Choices, [&](ArrayRef<int> State) -> bool {
  CombinationGenerator<int, std::vector<int>, 4> G(Choices);
  const size_t NumVariants = G.numCombinations();
  G.generate([&](ArrayRef<int> State) -> bool {
    Variants.emplace_back(State);
    return false; // keep going
  });
  const size_t NumVariants = G.numCombinations();
  G.generate();

  const std::vector<std::vector<int>> ExpectedVariants{
      {0, 2},
@@ -104,13 +100,12 @@ TEST(CombinationGenerator, RightColumn) {
  const std::vector<std::vector<int>> Choices{{0}, {1, 2}};

  std::vector<std::vector<int>> Variants;
  CombinationGenerator<int, std::vector<int>, 4> G(
      Choices, [&](ArrayRef<int> State) -> bool {
  CombinationGenerator<int, std::vector<int>, 4> G(Choices);
  const size_t NumVariants = G.numCombinations();
  G.generate([&](ArrayRef<int> State) -> bool {
    Variants.emplace_back(State);
    return false; // keep going
  });
  const size_t NumVariants = G.numCombinations();
  G.generate();

  const std::vector<std::vector<int>> ExpectedVariants{
      {0, 1},
@@ -124,13 +119,12 @@ TEST(CombinationGenerator, Column) {
  const std::vector<std::vector<int>> Choices{{0, 1}};

  std::vector<std::vector<int>> Variants;
  CombinationGenerator<int, std::vector<int>, 4> G(
      Choices, [&](ArrayRef<int> State) -> bool {
  CombinationGenerator<int, std::vector<int>, 4> G(Choices);
  const size_t NumVariants = G.numCombinations();
  G.generate([&](ArrayRef<int> State) -> bool {
    Variants.emplace_back(State);
    return false; // keep going
  });
  const size_t NumVariants = G.numCombinations();
  G.generate();

  const std::vector<std::vector<int>> ExpectedVariants{
      {0},
@@ -144,13 +138,12 @@ TEST(CombinationGenerator, Row) {
  const std::vector<std::vector<int>> Choices{{0}, {1}};

  std::vector<std::vector<int>> Variants;
  CombinationGenerator<int, std::vector<int>, 4> G(
      Choices, [&](ArrayRef<int> State) -> bool {
  CombinationGenerator<int, std::vector<int>, 4> G(Choices);
  const size_t NumVariants = G.numCombinations();
  G.generate([&](ArrayRef<int> State) -> bool {
    Variants.emplace_back(State);
    return false; // keep going
  });
  const size_t NumVariants = G.numCombinations();
  G.generate();

  const std::vector<std::vector<int>> ExpectedVariants{
      {0, 1},
@@ -163,13 +156,12 @@ TEST(CombinationGenerator, Singleton) {
  const std::vector<std::vector<int>> Choices{{0}};

  std::vector<std::vector<int>> Variants;
  CombinationGenerator<int, std::vector<int>, 4> G(
      Choices, [&](ArrayRef<int> State) -> bool {
  CombinationGenerator<int, std::vector<int>, 4> G(Choices);
  const size_t NumVariants = G.numCombinations();
  G.generate([&](ArrayRef<int> State) -> bool {
    Variants.emplace_back(State);
    return false; // keep going
  });
  const size_t NumVariants = G.numCombinations();
  G.generate();

  const std::vector<std::vector<int>> ExpectedVariants{
      {0},