// Copyright (c) 2018 Google LLC.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "opt/loop_dependence.h"

#include <functional>
#include <memory>
#include <numeric>
#include <string>
#include <utility>
#include <vector>

#include "opt/instruction.h"
#include "opt/scalar_analysis.h"
#include "opt/scalar_analysis_nodes.h"

namespace spvtools {
namespace opt {

using SubscriptPair = std::pair<SENode*, SENode*>;

namespace {

// Calculate the greatest common divisor of a & b using Stein's algorithm.
// https://en.wikipedia.org/wiki/Binary_GCD_algorithm
int64_t GreatestCommonDivisor(int64_t a, int64_t b) {
  // Simple cases
  if (a == b) {
    return a;
  } else if (a == 0) {
    return b;
  } else if (b == 0) {
    return a;
  }

  // Both even
  if (a % 2 == 0 && b % 2 == 0) {
    return 2 * GreatestCommonDivisor(a / 2, b / 2);
  }

  // Even a, odd b
  if (a % 2 == 0 && b % 2 == 1) {
    return GreatestCommonDivisor(a / 2, b);
  }

  // Odd a, even b
  if (a % 2 == 1 && b % 2 == 0) {
    return GreatestCommonDivisor(a, b / 2);
  }

  // Both odd, reduce the larger argument
  if (a > b) {
    return GreatestCommonDivisor((a - b) / 2, b);
  } else {
    return GreatestCommonDivisor((b - a) / 2, a);
  }
}

// Check if node is affine, ie in the form: a0*i0 + a1*i1 + ... an*in + c
// and contains only the following types of nodes: SERecurrentNode, SEAddNode
// and SEConstantNode
bool IsInCorrectFormForGCDTest(SENode* node) {
  bool children_ok = true;

  if (auto add_node = node->AsSEAddNode()) {
    for (auto child : add_node->GetChildren()) {
      children_ok &= IsInCorrectFormForGCDTest(child);
    }
  }

  bool this_ok = node->AsSERecurrentNode() || node->AsSEAddNode() ||
                 node->AsSEConstantNode();

  return children_ok && this_ok;
}

// If |node| is an SERecurrentNode then returns |node| or if |node| is an
// SEAddNode returns a vector of SERecurrentNode that are its children.
std::vector<SERecurrentNode*> GetAllTopLevelRecurrences(SENode* node) {
  auto nodes = std::vector<SERecurrentNode*>{};
  if (auto recurrent_node = node->AsSERecurrentNode()) {
    nodes.push_back(recurrent_node);
  }

  if (auto add_node = node->AsSEAddNode()) {
    for (auto child : add_node->GetChildren()) {
      auto child_nodes = GetAllTopLevelRecurrences(child);
      nodes.insert(nodes.end(), child_nodes.begin(), child_nodes.end());
    }
  }

  return nodes;
}

// If |node| is an SEConstantNode then returns |node| or if |node| is an
// SEAddNode returns a vector of SEConstantNode that are its children.
std::vector<SEConstantNode*> GetAllTopLevelConstants(SENode* node) {
  auto nodes = std::vector<SEConstantNode*>{};
  if (auto recurrent_node = node->AsSEConstantNode()) {
    nodes.push_back(recurrent_node);
  }

  if (auto add_node = node->AsSEAddNode()) {
    for (auto child : add_node->GetChildren()) {
      auto child_nodes = GetAllTopLevelConstants(child);
      nodes.insert(nodes.end(), child_nodes.begin(), child_nodes.end());
    }
  }

  return nodes;
}

bool AreOffsetsAndCoefficientsConstant(
    const std::vector<SERecurrentNode*>& nodes) {
  for (auto node : nodes) {
    if (!node->GetOffset()->AsSEConstantNode() ||
        !node->GetOffset()->AsSEConstantNode()) {
      return false;
    }
  }
  return true;
}

// Fold all SEConstantNode that appear in |recurrences| and |constants| into a
// single integer value.
int64_t CalculateConstantTerm(const std::vector<SERecurrentNode*>& recurrences,
                              const std::vector<SEConstantNode*>& constants) {
  int64_t constant_term = 0;
  for (auto recurrence : recurrences) {
    constant_term +=
        recurrence->GetOffset()->AsSEConstantNode()->FoldToSingleValue();
  }

  for (auto constant : constants) {
    constant_term += constant->FoldToSingleValue();
  }

  return constant_term;
}

int64_t CalculateGCDFromCoefficients(
    const std::vector<SERecurrentNode*>& recurrences, int64_t running_gcd) {
  for (SERecurrentNode* recurrence : recurrences) {
    auto coefficient = recurrence->GetCoefficient()->AsSEConstantNode();

    running_gcd = GreatestCommonDivisor(
        running_gcd, std::abs(coefficient->FoldToSingleValue()));
  }

  return running_gcd;
}

// Compare 2 fractions while first normalizing them, e.g. 2/4 and 4/8 will both
// be simplified to 1/2 and then determined to be equal.
bool NormalizeAndCompareFractions(int64_t numerator_0, int64_t denominator_0,
                                  int64_t numerator_1, int64_t denominator_1) {
  auto gcd_0 =
      GreatestCommonDivisor(std::abs(numerator_0), std::abs(denominator_0));
  auto gcd_1 =
      GreatestCommonDivisor(std::abs(numerator_1), std::abs(denominator_1));

  auto normalized_numerator_0 = numerator_0 / gcd_0;
  auto normalized_denominator_0 = denominator_0 / gcd_0;
  auto normalized_numerator_1 = numerator_1 / gcd_1;
  auto normalized_denominator_1 = denominator_1 / gcd_1;

  return normalized_numerator_0 == normalized_numerator_1 &&
         normalized_denominator_0 == normalized_denominator_1;
}

}  // namespace

bool LoopDependenceAnalysis::GetDependence(const ir::Instruction* source,
                                           const ir::Instruction* destination,
                                           DistanceVector* distance_vector) {
  // Start off by finding and marking all the loops in |loops_| that are
  // irrelevant to the dependence analysis.
  MarkUnsusedDistanceEntriesAsIrrelevant(source, destination, distance_vector);

  ir::Instruction* source_access_chain = GetOperandDefinition(source, 0);
  ir::Instruction* destination_access_chain =
      GetOperandDefinition(destination, 0);

  // If the access chains aren't collecting from the same structure there is no
  // dependence.
  ir::Instruction* source_array = GetOperandDefinition(source_access_chain, 0);
  ir::Instruction* destination_array =
      GetOperandDefinition(destination_access_chain, 0);
  if (source_array != destination_array) {
    PrintDebug("Proved independence through different arrays.");
    return true;
  }

  // To handle multiple subscripts we must get every operand in the access
  // chains past the first.
  std::vector<ir::Instruction*> source_subscripts = GetSubscripts(source);
  std::vector<ir::Instruction*> destination_subscripts =
      GetSubscripts(destination);

  auto sets_of_subscripts =
      PartitionSubscripts(source_subscripts, destination_subscripts);

  auto first_coupled = std::partition(
      std::begin(sets_of_subscripts), std::end(sets_of_subscripts),
      [](const std::set<std::pair<ir::Instruction*, ir::Instruction*>>& set) {
        return set.size() == 1;
      });

  // Go through each subscript testing for independence.
  // If any subscript results in independence, we prove independence between the
  // load and store.
  // If we can't prove independence we store what information we can gather in
  // a DistanceVector.
  for (auto it = std::begin(sets_of_subscripts); it < first_coupled; ++it) {
    auto source_subscript = std::get<0>(*(*it).begin());
    auto destination_subscript = std::get<1>(*(*it).begin());

    SENode* source_node = scalar_evolution_.SimplifyExpression(
        scalar_evolution_.AnalyzeInstruction(source_subscript));
    SENode* destination_node = scalar_evolution_.SimplifyExpression(
        scalar_evolution_.AnalyzeInstruction(destination_subscript));

    // Check the loops are in a form we support.
    auto subscript_pair = std::make_pair(source_node, destination_node);

    const ir::Loop* loop = GetLoopForSubscriptPair(subscript_pair);
    if (loop) {
      if (!IsSupportedLoop(loop)) {
        PrintDebug(
            "GetDependence found an unsupported loop form. Assuming <=> for "
            "loop.");
        DistanceEntry* distance_entry =
            GetDistanceEntryForSubscriptPair(subscript_pair, distance_vector);
        if (distance_entry) {
          distance_entry->direction = DistanceEntry::Directions::ALL;
        }
        continue;
      }
    }

    // If either node is simplified to a CanNotCompute we can't perform any
    // analysis so must assume <=> dependence and return.
    if (source_node->GetType() == SENode::CanNotCompute ||
        destination_node->GetType() == SENode::CanNotCompute) {
      // Record the <=> dependence if we can get a DistanceEntry
      PrintDebug(
          "GetDependence found source_node || destination_node as "
          "CanNotCompute. Abandoning evaluation for this subscript.");
      DistanceEntry* distance_entry =
          GetDistanceEntryForSubscriptPair(subscript_pair, distance_vector);
      if (distance_entry) {
        distance_entry->direction = DistanceEntry::Directions::ALL;
      }
      continue;
    }

    // We have no induction variables so can apply a ZIV test.
    if (IsZIV(subscript_pair)) {
      PrintDebug("Found a ZIV subscript pair");
      if (ZIVTest(subscript_pair)) {
        PrintDebug("Proved independence with ZIVTest.");
        return true;
      }
    }

    // We have only one induction variable so should attempt an SIV test.
    if (IsSIV(subscript_pair)) {
      PrintDebug("Found a SIV subscript pair.");
      if (SIVTest(subscript_pair, distance_vector)) {
        PrintDebug("Proved independence with SIVTest.");
        return true;
      }
    }

    // We have multiple induction variables so should attempt an MIV test.
    if (IsMIV(subscript_pair)) {
      PrintDebug("Found a MIV subscript pair.");
      if (GCDMIVTest(subscript_pair)) {
        PrintDebug("Proved independence with the GCD test.");
        auto current_loops = CollectLoops(source_node, destination_node);

        for (auto current_loop : current_loops) {
          auto distance_entry =
              GetDistanceEntryForLoop(current_loop, distance_vector);
          distance_entry->direction = DistanceEntry::Directions::NONE;
        }
        return true;
      }
    }
  }

  for (auto it = first_coupled; it < std::end(sets_of_subscripts); ++it) {
    auto coupled_instructions = *it;
    std::vector<SubscriptPair> coupled_subscripts{};

    for (const auto& elem : coupled_instructions) {
      auto source_subscript = std::get<0>(elem);
      auto destination_subscript = std::get<1>(elem);

      SENode* source_node = scalar_evolution_.SimplifyExpression(
          scalar_evolution_.AnalyzeInstruction(source_subscript));
      SENode* destination_node = scalar_evolution_.SimplifyExpression(
          scalar_evolution_.AnalyzeInstruction(destination_subscript));

      coupled_subscripts.push_back({source_node, destination_node});
    }

    auto supported = true;

    for (const auto& subscript : coupled_subscripts) {
      auto loops = CollectLoops(std::get<0>(subscript), std::get<1>(subscript));

      auto is_subscript_supported =
          std::all_of(std::begin(loops), std::end(loops),
                      [this](const ir::Loop* l) { return IsSupportedLoop(l); });

      supported = supported && is_subscript_supported;
    }

    if (DeltaTest(coupled_subscripts, distance_vector)) {
      return true;
    }
  }

  // We were unable to prove independence so must gather all of the direction
  // information we found.
  PrintDebug(
      "Couldn't prove independence.\n"
      "All possible direction information has been collected in the input "
      "DistanceVector.");

  return false;
}

bool LoopDependenceAnalysis::ZIVTest(
    const std::pair<SENode*, SENode*>& subscript_pair) {
  auto source = std::get<0>(subscript_pair);
  auto destination = std::get<1>(subscript_pair);

  PrintDebug("Performing ZIVTest");
  // If source == destination, dependence with direction = and distance 0.
  if (source == destination) {
    PrintDebug("ZIVTest found EQ dependence.");
    return false;
  } else {
    PrintDebug("ZIVTest found independence.");
    // Otherwise we prove independence.
    return true;
  }
}

bool LoopDependenceAnalysis::SIVTest(
    const std::pair<SENode*, SENode*>& subscript_pair,
    DistanceVector* distance_vector) {
  DistanceEntry* distance_entry =
      GetDistanceEntryForSubscriptPair(subscript_pair, distance_vector);
  if (!distance_entry) {
    PrintDebug(
        "SIVTest could not find a DistanceEntry for subscript_pair. Exiting");
  }

  SENode* source_node = std::get<0>(subscript_pair);
  SENode* destination_node = std::get<1>(subscript_pair);

  int64_t source_induction_count = CountInductionVariables(source_node);
  int64_t destination_induction_count =
      CountInductionVariables(destination_node);

  // If the source node has no induction variables we can apply a
  // WeakZeroSrcTest.
  if (source_induction_count == 0) {
    PrintDebug("Found source has no induction variable.");
    if (WeakZeroSourceSIVTest(
            source_node, destination_node->AsSERecurrentNode(),
            destination_node->AsSERecurrentNode()->GetCoefficient(),
            distance_entry)) {
      PrintDebug("Proved independence with WeakZeroSourceSIVTest.");
      distance_entry->dependence_information =
          DistanceEntry::DependenceInformation::DIRECTION;
      distance_entry->direction = DistanceEntry::Directions::NONE;
      return true;
    }
  }

  // If the destination has no induction variables we can apply a
  // WeakZeroDestTest.
  if (destination_induction_count == 0) {
    PrintDebug("Found destination has no induction variable.");
    if (WeakZeroDestinationSIVTest(
            source_node->AsSERecurrentNode(), destination_node,
            source_node->AsSERecurrentNode()->GetCoefficient(),
            distance_entry)) {
      PrintDebug("Proved independence with WeakZeroDestinationSIVTest.");
      distance_entry->dependence_information =
          DistanceEntry::DependenceInformation::DIRECTION;
      distance_entry->direction = DistanceEntry::Directions::NONE;
      return true;
    }
  }

  // We now need to collect the SERecurrentExpr nodes from source and
  // destination. We do not handle cases where source or destination have
  // multiple SERecurrentExpr nodes.
  std::vector<SERecurrentNode*> source_recurrent_nodes =
      source_node->CollectRecurrentNodes();
  std::vector<SERecurrentNode*> destination_recurrent_nodes =
      destination_node->CollectRecurrentNodes();

  if (source_recurrent_nodes.size() == 1 &&
      destination_recurrent_nodes.size() == 1) {
    PrintDebug("Found source and destination have 1 induction variable.");
    SERecurrentNode* source_recurrent_expr = *source_recurrent_nodes.begin();
    SERecurrentNode* destination_recurrent_expr =
        *destination_recurrent_nodes.begin();

    // If the coefficients are identical we can apply a StrongSIVTest.
    if (source_recurrent_expr->GetCoefficient() ==
        destination_recurrent_expr->GetCoefficient()) {
      PrintDebug("Found source and destination share coefficient.");
      if (StrongSIVTest(source_node, destination_node,
                        source_recurrent_expr->GetCoefficient(),
                        distance_entry)) {
        PrintDebug("Proved independence with StrongSIVTest");
        distance_entry->dependence_information =
            DistanceEntry::DependenceInformation::DIRECTION;
        distance_entry->direction = DistanceEntry::Directions::NONE;
        return true;
      }
    }

    // If the coefficients are of equal magnitude and opposite sign we can
    // apply a WeakCrossingSIVTest.
    if (source_recurrent_expr->GetCoefficient() ==
        scalar_evolution_.CreateNegation(
            destination_recurrent_expr->GetCoefficient())) {
      PrintDebug("Found source coefficient = -destination coefficient.");
      if (WeakCrossingSIVTest(source_node, destination_node,
                              source_recurrent_expr->GetCoefficient(),
                              distance_entry)) {
        PrintDebug("Proved independence with WeakCrossingSIVTest");
        distance_entry->dependence_information =
            DistanceEntry::DependenceInformation::DIRECTION;
        distance_entry->direction = DistanceEntry::Directions::NONE;
        return true;
      }
    }
  }

  return false;
}

bool LoopDependenceAnalysis::StrongSIVTest(SENode* source, SENode* destination,
                                           SENode* coefficient,
                                           DistanceEntry* distance_entry) {
  PrintDebug("Performing StrongSIVTest.");
  // If both source and destination are SERecurrentNodes we can perform tests
  // based on distance.
  // If either source or destination contain value unknown nodes or if one or
  // both are not SERecurrentNodes we must attempt a symbolic test.
  std::vector<SEValueUnknown*> source_value_unknown_nodes =
      source->CollectValueUnknownNodes();
  std::vector<SEValueUnknown*> destination_value_unknown_nodes =
      destination->CollectValueUnknownNodes();
  if (source_value_unknown_nodes.size() > 0 ||
      destination_value_unknown_nodes.size() > 0) {
    PrintDebug(
        "StrongSIVTest found symbolics. Will attempt SymbolicStrongSIVTest.");
    return SymbolicStrongSIVTest(source, destination, coefficient,
                                 distance_entry);
  }

  if (!source->AsSERecurrentNode() || !destination->AsSERecurrentNode()) {
    PrintDebug(
        "StrongSIVTest could not simplify source and destination to "
        "SERecurrentNodes so will exit.");
    distance_entry->direction = DistanceEntry::Directions::ALL;
    return false;
  }

  // Build an SENode for distance.
  std::pair<SENode*, SENode*> subscript_pair =
      std::make_pair(source, destination);
  const ir::Loop* subscript_loop = GetLoopForSubscriptPair(subscript_pair);
  SENode* source_constant_term =
      GetConstantTerm(subscript_loop, source->AsSERecurrentNode());
  SENode* destination_constant_term =
      GetConstantTerm(subscript_loop, destination->AsSERecurrentNode());
  if (!source_constant_term || !destination_constant_term) {
    PrintDebug(
        "StrongSIVTest could not collect the constant terms of either source "
        "or destination so will exit.");
    return false;
  }
  SENode* constant_term_delta =
      scalar_evolution_.SimplifyExpression(scalar_evolution_.CreateSubtraction(
          destination_constant_term, source_constant_term));

  // Scalar evolution doesn't perform division, so we must fold to constants and
  // do it manually.
  // We must check the offset delta and coefficient are constants.
  int64_t distance = 0;
  SEConstantNode* delta_constant = constant_term_delta->AsSEConstantNode();
  SEConstantNode* coefficient_constant = coefficient->AsSEConstantNode();
  if (delta_constant && coefficient_constant) {
    int64_t delta_value = delta_constant->FoldToSingleValue();
    int64_t coefficient_value = coefficient_constant->FoldToSingleValue();
    PrintDebug(
        "StrongSIVTest found delta value and coefficient value as constants "
        "with values:\n"
        "\tdelta value: " +
        ToString(delta_value) +
        "\n\tcoefficient value: " + ToString(coefficient_value) + "\n");
    // Check if the distance is not integral to try to prove independence.
    if (delta_value % coefficient_value != 0) {
      PrintDebug(
          "StrongSIVTest proved independence through distance not being an "
          "integer.");
      distance_entry->dependence_information =
          DistanceEntry::DependenceInformation::DIRECTION;
      distance_entry->direction = DistanceEntry::Directions::NONE;
      return true;
    } else {
      distance = delta_value / coefficient_value;
      PrintDebug("StrongSIV test found distance as " + ToString(distance));
    }
  } else {
    // If we can't fold delta and coefficient to single values we can't produce
    // distance.
    // As a result we can't perform the rest of the pass and must assume
    // dependence in all directions.
    PrintDebug("StrongSIVTest could not produce a distance. Must exit.");
    distance_entry->distance = DistanceEntry::Directions::ALL;
    return false;
  }

  // Next we gather the upper and lower bounds as constants if possible. If
  // distance > upper_bound - lower_bound we prove independence.
  SENode* lower_bound = GetLowerBound(subscript_loop);
  SENode* upper_bound = GetUpperBound(subscript_loop);
  if (lower_bound && upper_bound) {
    PrintDebug("StrongSIVTest found bounds.");
    SENode* bounds = scalar_evolution_.SimplifyExpression(
        scalar_evolution_.CreateSubtraction(upper_bound, lower_bound));

    if (bounds->GetType() == SENode::SENodeType::Constant) {
      int64_t bounds_value = bounds->AsSEConstantNode()->FoldToSingleValue();
      PrintDebug(
          "StrongSIVTest found upper_bound - lower_bound as a constant with "
          "value " +
          ToString(bounds_value));

      // If the absolute value of the distance is > upper bound - lower bound
      // then we prove independence.
      if (llabs(distance) > llabs(bounds_value)) {
        PrintDebug(
            "StrongSIVTest proved independence through distance escaping the "
            "loop bounds.");
        distance_entry->dependence_information =
            DistanceEntry::DependenceInformation::DISTANCE;
        distance_entry->direction = DistanceEntry::Directions::NONE;
        distance_entry->distance = distance;
        return true;
      }
    }
  } else {
    PrintDebug("StrongSIVTest was unable to gather lower and upper bounds.");
  }

  // Otherwise we can get a direction as follows
  //             { < if distance > 0
  // direction = { = if distance == 0
  //             { > if distance < 0
  PrintDebug(
      "StrongSIVTest could not prove independence. Gathering direction "
      "information.");
  if (distance > 0) {
    distance_entry->dependence_information =
        DistanceEntry::DependenceInformation::DISTANCE;
    distance_entry->direction = DistanceEntry::Directions::LT;
    distance_entry->distance = distance;
    return false;
  }
  if (distance == 0) {
    distance_entry->dependence_information =
        DistanceEntry::DependenceInformation::DISTANCE;
    distance_entry->direction = DistanceEntry::Directions::EQ;
    distance_entry->distance = 0;
    return false;
  }
  if (distance < 0) {
    distance_entry->dependence_information =
        DistanceEntry::DependenceInformation::DISTANCE;
    distance_entry->direction = DistanceEntry::Directions::GT;
    distance_entry->distance = distance;
    return false;
  }

  // We were unable to prove independence or discern any additional information
  // Must assume <=> direction.
  PrintDebug(
      "StrongSIVTest was unable to determine any dependence information.");
  distance_entry->direction = DistanceEntry::Directions::ALL;
  return false;
}

bool LoopDependenceAnalysis::SymbolicStrongSIVTest(
    SENode* source, SENode* destination, SENode* coefficient,
    DistanceEntry* distance_entry) {
  PrintDebug("Performing SymbolicStrongSIVTest.");
  SENode* source_destination_delta = scalar_evolution_.SimplifyExpression(
      scalar_evolution_.CreateSubtraction(source, destination));
  // By cancelling out the induction variables by subtracting the source and
  // destination we can produce an expression of symbolics and constants. This
  // expression can be compared to the loop bounds to find if the offset is
  // outwith the bounds.
  std::pair<SENode*, SENode*> subscript_pair =
      std::make_pair(source, destination);
  const ir::Loop* subscript_loop = GetLoopForSubscriptPair(subscript_pair);
  if (IsProvablyOutsideOfLoopBounds(subscript_loop, source_destination_delta,
                                    coefficient)) {
    PrintDebug(
        "SymbolicStrongSIVTest proved independence through loop bounds.");
    distance_entry->dependence_information =
        DistanceEntry::DependenceInformation::DIRECTION;
    distance_entry->direction = DistanceEntry::Directions::NONE;
    return true;
  }
  // We were unable to prove independence or discern any additional information.
  // Must assume <=> direction.
  PrintDebug(
      "SymbolicStrongSIVTest was unable to determine any dependence "
      "information.");
  distance_entry->direction = DistanceEntry::Directions::ALL;
  return false;
}

bool LoopDependenceAnalysis::WeakZeroSourceSIVTest(
    SENode* source, SERecurrentNode* destination, SENode* coefficient,
    DistanceEntry* distance_entry) {
  PrintDebug("Performing WeakZeroSourceSIVTest.");
  std::pair<SENode*, SENode*> subscript_pair =
      std::make_pair(source, destination);
  const ir::Loop* subscript_loop = GetLoopForSubscriptPair(subscript_pair);
  // Build an SENode for distance.
  SENode* destination_constant_term =
      GetConstantTerm(subscript_loop, destination);
  SENode* delta = scalar_evolution_.SimplifyExpression(
      scalar_evolution_.CreateSubtraction(source, destination_constant_term));

  // Scalar evolution doesn't perform division, so we must fold to constants and
  // do it manually.
  int64_t distance = 0;
  SEConstantNode* delta_constant = delta->AsSEConstantNode();
  SEConstantNode* coefficient_constant = coefficient->AsSEConstantNode();
  if (delta_constant && coefficient_constant) {
    PrintDebug(
        "WeakZeroSourceSIVTest folding delta and coefficient to constants.");
    int64_t delta_value = delta_constant->FoldToSingleValue();
    int64_t coefficient_value = coefficient_constant->FoldToSingleValue();
    // Check if the distance is not integral.
    if (delta_value % coefficient_value != 0) {
      PrintDebug(
          "WeakZeroSourceSIVTest proved independence through distance not "
          "being an integer.");
      distance_entry->dependence_information =
          DistanceEntry::DependenceInformation::DIRECTION;
      distance_entry->direction = DistanceEntry::Directions::NONE;
      return true;
    } else {
      distance = delta_value / coefficient_value;
      PrintDebug(
          "WeakZeroSourceSIVTest calculated distance with the following "
          "values\n"
          "\tdelta value: " +
          ToString(delta_value) +
          "\n\tcoefficient value: " + ToString(coefficient_value) +
          "\n\tdistance: " + ToString(distance) + "\n");
    }
  } else {
    PrintDebug(
        "WeakZeroSourceSIVTest was unable to fold delta and coefficient to "
        "constants.");
  }

  // If we can prove the distance is outside the bounds we prove independence.
  SEConstantNode* lower_bound =
      GetLowerBound(subscript_loop)->AsSEConstantNode();
  SEConstantNode* upper_bound =
      GetUpperBound(subscript_loop)->AsSEConstantNode();
  if (lower_bound && upper_bound) {
    PrintDebug("WeakZeroSourceSIVTest found bounds as SEConstantNodes.");
    int64_t lower_bound_value = lower_bound->FoldToSingleValue();
    int64_t upper_bound_value = upper_bound->FoldToSingleValue();
    if (!IsWithinBounds(llabs(distance), lower_bound_value,
                        upper_bound_value)) {
      PrintDebug(
          "WeakZeroSourceSIVTest proved independence through distance escaping "
          "the loop bounds.");
      PrintDebug(
          "Bound values were as follow\n"
          "\tlower bound value: " +
          ToString(lower_bound_value) +
          "\n\tupper bound value: " + ToString(upper_bound_value) +
          "\n\tdistance value: " + ToString(distance) + "\n");
      distance_entry->dependence_information =
          DistanceEntry::DependenceInformation::DISTANCE;
      distance_entry->direction = DistanceEntry::Directions::NONE;
      distance_entry->distance = distance;
      return true;
    }
  } else {
    PrintDebug(
        "WeakZeroSourceSIVTest was unable to find lower and upper bound as "
        "SEConstantNodes.");
  }

  // Now we want to see if we can detect to peel the first or last iterations.

  // We get the FirstTripValue as GetFirstTripInductionNode() +
  // GetConstantTerm(destination)
  SENode* first_trip_SENode =
      scalar_evolution_.SimplifyExpression(scalar_evolution_.CreateAddNode(
          GetFirstTripInductionNode(subscript_loop),
          GetConstantTerm(subscript_loop, destination)));

  // If source == FirstTripValue, peel_first.
  if (first_trip_SENode) {
    PrintDebug("WeakZeroSourceSIVTest built first_trip_SENode.");
    if (first_trip_SENode->AsSEConstantNode()) {
      PrintDebug(
          "WeakZeroSourceSIVTest has found first_trip_SENode as an "
          "SEConstantNode with value: " +
          ToString(first_trip_SENode->AsSEConstantNode()->FoldToSingleValue()) +
          "\n");
    }
    if (source == first_trip_SENode) {
      // We have found that peeling the first iteration will break dependency.
      PrintDebug(
          "WeakZeroSourceSIVTest has found peeling first iteration will break "
          "dependency");
      distance_entry->dependence_information =
          DistanceEntry::DependenceInformation::PEEL;
      distance_entry->peel_first = true;
      return false;
    }
  } else {
    PrintDebug("WeakZeroSourceSIVTest was unable to build first_trip_SENode");
  }

  // We get the LastTripValue as GetFinalTripInductionNode(coefficient) +
  // GetConstantTerm(destination)
  SENode* final_trip_SENode =
      scalar_evolution_.SimplifyExpression(scalar_evolution_.CreateAddNode(
          GetFinalTripInductionNode(subscript_loop, coefficient),
          GetConstantTerm(subscript_loop, destination)));

  // If source == LastTripValue, peel_last.
  if (final_trip_SENode) {
    PrintDebug("WeakZeroSourceSIVTest built final_trip_SENode.");
    if (first_trip_SENode->AsSEConstantNode()) {
      PrintDebug(
          "WeakZeroSourceSIVTest has found final_trip_SENode as an "
          "SEConstantNode with value: " +
          ToString(final_trip_SENode->AsSEConstantNode()->FoldToSingleValue()) +
          "\n");
    }
    if (source == final_trip_SENode) {
      // We have found that peeling the last iteration will break dependency.
      PrintDebug(
          "WeakZeroSourceSIVTest has found peeling final iteration will break "
          "dependency");
      distance_entry->dependence_information =
          DistanceEntry::DependenceInformation::PEEL;
      distance_entry->peel_last = true;
      return false;
    }
  } else {
    PrintDebug("WeakZeroSourceSIVTest was unable to build final_trip_SENode");
  }

  // We were unable to prove independence or discern any additional information.
  // Must assume <=> direction.
  PrintDebug(
      "WeakZeroSourceSIVTest was unable to determine any dependence "
      "information.");
  distance_entry->direction = DistanceEntry::Directions::ALL;
  return false;
}

bool LoopDependenceAnalysis::WeakZeroDestinationSIVTest(
    SERecurrentNode* source, SENode* destination, SENode* coefficient,
    DistanceEntry* distance_entry) {
  PrintDebug("Performing WeakZeroDestinationSIVTest.");
  // Build an SENode for distance.
  std::pair<SENode*, SENode*> subscript_pair =
      std::make_pair(source, destination);
  const ir::Loop* subscript_loop = GetLoopForSubscriptPair(subscript_pair);
  SENode* source_constant_term = GetConstantTerm(subscript_loop, source);
  SENode* delta = scalar_evolution_.SimplifyExpression(
      scalar_evolution_.CreateSubtraction(destination, source_constant_term));

  // Scalar evolution doesn't perform division, so we must fold to constants and
  // do it manually.
  int64_t distance = 0;
  SEConstantNode* delta_constant = delta->AsSEConstantNode();
  SEConstantNode* coefficient_constant = coefficient->AsSEConstantNode();
  if (delta_constant && coefficient_constant) {
    PrintDebug(
        "WeakZeroDestinationSIVTest folding delta and coefficient to "
        "constants.");
    int64_t delta_value = delta_constant->FoldToSingleValue();
    int64_t coefficient_value = coefficient_constant->FoldToSingleValue();
    // Check if the distance is not integral.
    if (delta_value % coefficient_value != 0) {
      PrintDebug(
          "WeakZeroDestinationSIVTest proved independence through distance not "
          "being an integer.");
      distance_entry->dependence_information =
          DistanceEntry::DependenceInformation::DIRECTION;
      distance_entry->direction = DistanceEntry::Directions::NONE;
      return true;
    } else {
      distance = delta_value / coefficient_value;
      PrintDebug(
          "WeakZeroDestinationSIVTest calculated distance with the following "
          "values\n"
          "\tdelta value: " +
          ToString(delta_value) +
          "\n\tcoefficient value: " + ToString(coefficient_value) +
          "\n\tdistance: " + ToString(distance) + "\n");
    }
  } else {
    PrintDebug(
        "WeakZeroDestinationSIVTest was unable to fold delta and coefficient "
        "to constants.");
  }

  // If we can prove the distance is outside the bounds we prove independence.
  SEConstantNode* lower_bound =
      GetLowerBound(subscript_loop)->AsSEConstantNode();
  SEConstantNode* upper_bound =
      GetUpperBound(subscript_loop)->AsSEConstantNode();
  if (lower_bound && upper_bound) {
    PrintDebug("WeakZeroDestinationSIVTest found bounds as SEConstantNodes.");
    int64_t lower_bound_value = lower_bound->FoldToSingleValue();
    int64_t upper_bound_value = upper_bound->FoldToSingleValue();
    if (!IsWithinBounds(llabs(distance), lower_bound_value,
                        upper_bound_value)) {
      PrintDebug(
          "WeakZeroDestinationSIVTest proved independence through distance "
          "escaping the loop bounds.");
      PrintDebug(
          "Bound values were as follows\n"
          "\tlower bound value: " +
          ToString(lower_bound_value) +
          "\n\tupper bound value: " + ToString(upper_bound_value) +
          "\n\tdistance value: " + ToString(distance));
      distance_entry->dependence_information =
          DistanceEntry::DependenceInformation::DISTANCE;
      distance_entry->direction = DistanceEntry::Directions::NONE;
      distance_entry->distance = distance;
      return true;
    }
  } else {
    PrintDebug(
        "WeakZeroDestinationSIVTest was unable to find lower and upper bound "
        "as SEConstantNodes.");
  }

  // Now we want to see if we can detect to peel the first or last iterations.

  // We get the FirstTripValue as GetFirstTripInductionNode() +
  // GetConstantTerm(source)
  SENode* first_trip_SENode = scalar_evolution_.SimplifyExpression(
      scalar_evolution_.CreateAddNode(GetFirstTripInductionNode(subscript_loop),
                                      GetConstantTerm(subscript_loop, source)));

  // If destination == FirstTripValue, peel_first.
  if (first_trip_SENode) {
    PrintDebug("WeakZeroDestinationSIVTest built first_trip_SENode.");
    if (first_trip_SENode->AsSEConstantNode()) {
      PrintDebug(
          "WeakZeroDestinationSIVTest has found first_trip_SENode as an "
          "SEConstantNode with value: " +
          ToString(first_trip_SENode->AsSEConstantNode()->FoldToSingleValue()) +
          "\n");
    }
    if (destination == first_trip_SENode) {
      // We have found that peeling the first iteration will break dependency.
      PrintDebug(
          "WeakZeroDestinationSIVTest has found peeling first iteration will "
          "break dependency");
      distance_entry->dependence_information =
          DistanceEntry::DependenceInformation::PEEL;
      distance_entry->peel_first = true;
      return false;
    }
  } else {
    PrintDebug(
        "WeakZeroDestinationSIVTest was unable to build first_trip_SENode");
  }

  // We get the LastTripValue as GetFinalTripInductionNode(coefficient) +
  // GetConstantTerm(source)
  SENode* final_trip_SENode =
      scalar_evolution_.SimplifyExpression(scalar_evolution_.CreateAddNode(
          GetFinalTripInductionNode(subscript_loop, coefficient),
          GetConstantTerm(subscript_loop, source)));

  // If destination == LastTripValue, peel_last.
  if (final_trip_SENode) {
    PrintDebug("WeakZeroDestinationSIVTest built final_trip_SENode.");
    if (final_trip_SENode->AsSEConstantNode()) {
      PrintDebug(
          "WeakZeroDestinationSIVTest has found final_trip_SENode as an "
          "SEConstantNode with value: " +
          ToString(final_trip_SENode->AsSEConstantNode()->FoldToSingleValue()) +
          "\n");
    }
    if (destination == final_trip_SENode) {
      // We have found that peeling the last iteration will break dependency.
      PrintDebug(
          "WeakZeroDestinationSIVTest has found peeling final iteration will "
          "break dependency");
      distance_entry->dependence_information =
          DistanceEntry::DependenceInformation::PEEL;
      distance_entry->peel_last = true;
      return false;
    }
  } else {
    PrintDebug(
        "WeakZeroDestinationSIVTest was unable to build final_trip_SENode");
  }

  // We were unable to prove independence or discern any additional information.
  // Must assume <=> direction.
  PrintDebug(
      "WeakZeroDestinationSIVTest was unable to determine any dependence "
      "information.");
  distance_entry->direction = DistanceEntry::Directions::ALL;
  return false;
}

bool LoopDependenceAnalysis::WeakCrossingSIVTest(
    SENode* source, SENode* destination, SENode* coefficient,
    DistanceEntry* distance_entry) {
  PrintDebug("Performing WeakCrossingSIVTest.");
  // We currently can't handle symbolic WeakCrossingSIVTests. If either source
  // or destination are not SERecurrentNodes we must exit.
  if (!source->AsSERecurrentNode() || !destination->AsSERecurrentNode()) {
    PrintDebug(
        "WeakCrossingSIVTest found source or destination != SERecurrentNode. "
        "Exiting");
    distance_entry->direction = DistanceEntry::Directions::ALL;
    return false;
  }

  // Build an SENode for distance.
  SENode* offset_delta =
      scalar_evolution_.SimplifyExpression(scalar_evolution_.CreateSubtraction(
          destination->AsSERecurrentNode()->GetOffset(),
          source->AsSERecurrentNode()->GetOffset()));

  // Scalar evolution doesn't perform division, so we must fold to constants and
  // do it manually.
  int64_t distance = 0;
  SEConstantNode* delta_constant = offset_delta->AsSEConstantNode();
  SEConstantNode* coefficient_constant = coefficient->AsSEConstantNode();
  if (delta_constant && coefficient_constant) {
    PrintDebug(
        "WeakCrossingSIVTest folding offset_delta and coefficient to "
        "constants.");
    int64_t delta_value = delta_constant->FoldToSingleValue();
    int64_t coefficient_value = coefficient_constant->FoldToSingleValue();
    // Check if the distance is not integral or if it has a non-integral part
    // equal to 1/2.
    if (delta_value % (2 * coefficient_value) != 0 &&
        static_cast<float>(delta_value % (2 * coefficient_value)) /
                static_cast<float>(2 * coefficient_value) !=
            0.5) {
      PrintDebug(
          "WeakCrossingSIVTest proved independence through distance escaping "
          "the loop bounds.");
      distance_entry->dependence_information =
          DistanceEntry::DependenceInformation::DIRECTION;
      distance_entry->direction = DistanceEntry::Directions::NONE;
      return true;
    } else {
      distance = delta_value / (2 * coefficient_value);
    }

    if (distance == 0) {
      PrintDebug("WeakCrossingSIVTest found EQ dependence.");
      distance_entry->dependence_information =
          DistanceEntry::DependenceInformation::DISTANCE;
      distance_entry->direction = DistanceEntry::Directions::EQ;
      distance_entry->distance = 0;
      return false;
    }
  } else {
    PrintDebug(
        "WeakCrossingSIVTest was unable to fold offset_delta and coefficient "
        "to constants.");
  }

  // We were unable to prove independence or discern any additional information.
  // Must assume <=> direction.
  PrintDebug(
      "WeakCrossingSIVTest was unable to determine any dependence "
      "information.");
  distance_entry->direction = DistanceEntry::Directions::ALL;
  return false;
}

// Perform the GCD test if both, the source and the destination nodes, are in
// the form a0*i0 + a1*i1 + ... an*in + c.
bool LoopDependenceAnalysis::GCDMIVTest(
    const std::pair<SENode*, SENode*>& subscript_pair) {
  auto source = std::get<0>(subscript_pair);
  auto destination = std::get<1>(subscript_pair);

  // Bail out if source/destination is in an unexpected form.
  if (!IsInCorrectFormForGCDTest(source) ||
      !IsInCorrectFormForGCDTest(destination)) {
    return false;
  }

  auto source_recurrences = GetAllTopLevelRecurrences(source);
  auto dest_recurrences = GetAllTopLevelRecurrences(destination);

  // Bail out if all offsets and coefficients aren't constant.
  if (!AreOffsetsAndCoefficientsConstant(source_recurrences) ||
      !AreOffsetsAndCoefficientsConstant(dest_recurrences)) {
    return false;
  }

  // Calculate the GCD of all coefficients.
  auto source_constants = GetAllTopLevelConstants(source);
  int64_t source_constant =
      CalculateConstantTerm(source_recurrences, source_constants);

  auto dest_constants = GetAllTopLevelConstants(destination);
  int64_t destination_constant =
      CalculateConstantTerm(dest_recurrences, dest_constants);

  int64_t delta = std::abs(source_constant - destination_constant);

  int64_t running_gcd = 0;

  running_gcd = CalculateGCDFromCoefficients(source_recurrences, running_gcd);
  running_gcd = CalculateGCDFromCoefficients(dest_recurrences, running_gcd);

  return delta % running_gcd != 0;
}

using PartitionedSubscripts =
    std::vector<std::set<std::pair<ir::Instruction*, ir::Instruction*>>>;
PartitionedSubscripts LoopDependenceAnalysis::PartitionSubscripts(
    const std::vector<ir::Instruction*>& source_subscripts,
    const std::vector<ir::Instruction*>& destination_subscripts) {
  PartitionedSubscripts partitions{};

  auto num_subscripts = source_subscripts.size();

  // Create initial partitions with one subscript pair per partition.
  for (size_t i = 0; i < num_subscripts; ++i) {
    partitions.push_back({{source_subscripts[i], destination_subscripts[i]}});
  }

  // Iterate over the loops to create all partitions
  for (auto loop : loops_) {
    int64_t k = -1;

    for (size_t j = 0; j < partitions.size(); ++j) {
      auto& current_partition = partitions[j];

      // Does |loop| appear in |current_partition|
      auto it = std::find_if(
          current_partition.begin(), current_partition.end(),
          [loop,
           this](const std::pair<ir::Instruction*, ir::Instruction*>& elem)
              -> bool {
            auto source_recurrences =
                scalar_evolution_.AnalyzeInstruction(std::get<0>(elem))
                    ->CollectRecurrentNodes();
            auto destination_recurrences =
                scalar_evolution_.AnalyzeInstruction(std::get<1>(elem))
                    ->CollectRecurrentNodes();

            source_recurrences.insert(source_recurrences.end(),
                                      destination_recurrences.begin(),
                                      destination_recurrences.end());

            auto loops_in_pair = CollectLoops(source_recurrences);
            auto end_it = loops_in_pair.end();

            return std::find(loops_in_pair.begin(), end_it, loop) != end_it;
          });

      auto has_loop = it != current_partition.end();

      if (has_loop) {
        if (k == -1) {
          k = j;
        } else {
          // Add |partitions[j]| to |partitions[k]| and discard |partitions[j]|
          partitions[static_cast<size_t>(k)].insert(current_partition.begin(),
                                                    current_partition.end());
          current_partition.clear();
        }
      }
    }
  }

  // Remove empty (discarded) partitions
  partitions.erase(
      std::remove_if(
          partitions.begin(), partitions.end(),
          [](const std::set<std::pair<ir::Instruction*, ir::Instruction*>>&
                 partition) { return partition.empty(); }),
      partitions.end());

  return partitions;
}

Constraint* LoopDependenceAnalysis::IntersectConstraints(
    Constraint* constraint_0, Constraint* constraint_1,
    const SENode* lower_bound, const SENode* upper_bound) {
  if (constraint_0->AsDependenceNone()) {
    return constraint_1;
  } else if (constraint_1->AsDependenceNone()) {
    return constraint_0;
  }

  // Both constraints are distances. Either the same distance or independent.
  if (constraint_0->AsDependenceDistance() &&
      constraint_1->AsDependenceDistance()) {
    auto dist_0 = constraint_0->AsDependenceDistance();
    auto dist_1 = constraint_1->AsDependenceDistance();

    if (*dist_0->GetDistance() == *dist_1->GetDistance()) {
      return constraint_0;
    } else {
      return make_constraint<DependenceEmpty>();
    }
  }

  // Both constraints are points. Either the same point or independent.
  if (constraint_0->AsDependencePoint() && constraint_1->AsDependencePoint()) {
    auto point_0 = constraint_0->AsDependencePoint();
    auto point_1 = constraint_1->AsDependencePoint();

    if (*point_0->GetSource() == *point_1->GetSource() &&
        *point_0->GetDestination() == *point_1->GetDestination()) {
      return constraint_0;
    } else {
      return make_constraint<DependenceEmpty>();
    }
  }

  // Both constraints are lines/distances.
  if ((constraint_0->AsDependenceDistance() ||
       constraint_0->AsDependenceLine()) &&
      (constraint_1->AsDependenceDistance() ||
       constraint_1->AsDependenceLine())) {
    auto is_distance_0 = constraint_0->AsDependenceDistance() != nullptr;
    auto is_distance_1 = constraint_1->AsDependenceDistance() != nullptr;

    auto a0 = is_distance_0 ? scalar_evolution_.CreateConstant(1)
                            : constraint_0->AsDependenceLine()->GetA();
    auto b0 = is_distance_0 ? scalar_evolution_.CreateConstant(-1)
                            : constraint_0->AsDependenceLine()->GetB();
    auto c0 =
        is_distance_0
            ? scalar_evolution_.SimplifyExpression(
                  scalar_evolution_.CreateNegation(
                      constraint_0->AsDependenceDistance()->GetDistance()))
            : constraint_0->AsDependenceLine()->GetC();

    auto a1 = is_distance_1 ? scalar_evolution_.CreateConstant(1)
                            : constraint_1->AsDependenceLine()->GetA();
    auto b1 = is_distance_1 ? scalar_evolution_.CreateConstant(-1)
                            : constraint_1->AsDependenceLine()->GetB();
    auto c1 =
        is_distance_1
            ? scalar_evolution_.SimplifyExpression(
                  scalar_evolution_.CreateNegation(
                      constraint_1->AsDependenceDistance()->GetDistance()))
            : constraint_1->AsDependenceLine()->GetC();

    if (a0->AsSEConstantNode() && b0->AsSEConstantNode() &&
        c0->AsSEConstantNode() && a1->AsSEConstantNode() &&
        b1->AsSEConstantNode() && c1->AsSEConstantNode()) {
      auto constant_a0 = a0->AsSEConstantNode()->FoldToSingleValue();
      auto constant_b0 = b0->AsSEConstantNode()->FoldToSingleValue();
      auto constant_c0 = c0->AsSEConstantNode()->FoldToSingleValue();

      auto constant_a1 = a1->AsSEConstantNode()->FoldToSingleValue();
      auto constant_b1 = b1->AsSEConstantNode()->FoldToSingleValue();
      auto constant_c1 = c1->AsSEConstantNode()->FoldToSingleValue();

      // a & b can't both be zero, otherwise it wouldn't be line.
      if (NormalizeAndCompareFractions(constant_a0, constant_b0, constant_a1,
                                       constant_b1)) {
        // Slopes are equal, either parallel lines or the same line.

        if (constant_b0 == 0 && constant_b1 == 0) {
          if (NormalizeAndCompareFractions(constant_c0, constant_a0,
                                           constant_c1, constant_a1)) {
            return constraint_0;
          }

          return make_constraint<DependenceEmpty>();
        } else if (NormalizeAndCompareFractions(constant_c0, constant_b0,
                                                constant_c1, constant_b1)) {
          // Same line.
          return constraint_0;
        } else {
          // Parallel lines can't intersect, report independence.
          return make_constraint<DependenceEmpty>();
        }

      } else {
        // Lines are not parallel, therefore, they must intersect.

        // Calculate intersection.
        if (upper_bound->AsSEConstantNode() &&
            lower_bound->AsSEConstantNode()) {
          auto constant_lower_bound =
              lower_bound->AsSEConstantNode()->FoldToSingleValue();
          auto constant_upper_bound =
              upper_bound->AsSEConstantNode()->FoldToSingleValue();

          auto up = constant_b1 * constant_c0 - constant_b0 * constant_c1;
          // Both b or both a can't be 0, so down is never 0
          // otherwise would have entered the parallel line section.
          auto down = constant_b1 * constant_a0 - constant_b0 * constant_a1;

          auto x_coord = up / down;

          int64_t y_coord = 0;
          int64_t arg1 = 0;
          int64_t const_b_to_use = 0;

          if (constant_b1 != 0) {
            arg1 = constant_c1 - constant_a1 * x_coord;
            y_coord = arg1 / constant_b1;
            const_b_to_use = constant_b1;
          } else if (constant_b0 != 0) {
            arg1 = constant_c0 - constant_a0 * x_coord;
            y_coord = arg1 / constant_b0;
            const_b_to_use = constant_b0;
          }

          if (up % down == 0 &&
              arg1 % const_b_to_use == 0 &&  // Coordinates are integers.
              constant_lower_bound <=
                  x_coord &&  // x_coord is within loop bounds.
              x_coord <= constant_upper_bound &&
              constant_lower_bound <=
                  y_coord &&  // y_coord is within loop bounds.
              y_coord <= constant_upper_bound) {
            // Lines intersect at integer coordinates.
            return make_constraint<DependencePoint>(
                scalar_evolution_.CreateConstant(x_coord),
                scalar_evolution_.CreateConstant(y_coord),
                constraint_0->GetLoop());

          } else {
            return make_constraint<DependenceEmpty>();
          }

        } else {
          // Not constants, bail out.
          return make_constraint<DependenceNone>();
        }
      }

    } else {
      // Not constants, bail out.
      return make_constraint<DependenceNone>();
    }
  }

  // One constraint is a line/distance and the other is a point.
  if ((constraint_0->AsDependencePoint() &&
       (constraint_1->AsDependenceLine() ||
        constraint_1->AsDependenceDistance())) ||
      (constraint_1->AsDependencePoint() &&
       (constraint_0->AsDependenceLine() ||
        constraint_0->AsDependenceDistance()))) {
    auto point_0 = constraint_0->AsDependencePoint() != nullptr;

    auto point = point_0 ? constraint_0->AsDependencePoint()
                         : constraint_1->AsDependencePoint();

    auto line_or_distance = point_0 ? constraint_1 : constraint_0;

    auto is_distance = line_or_distance->AsDependenceDistance() != nullptr;

    auto a = is_distance ? scalar_evolution_.CreateConstant(1)
                         : line_or_distance->AsDependenceLine()->GetA();
    auto b = is_distance ? scalar_evolution_.CreateConstant(-1)
                         : line_or_distance->AsDependenceLine()->GetB();
    auto c =
        is_distance
            ? scalar_evolution_.SimplifyExpression(
                  scalar_evolution_.CreateNegation(
                      line_or_distance->AsDependenceDistance()->GetDistance()))
            : line_or_distance->AsDependenceLine()->GetC();

    auto x = point->GetSource();
    auto y = point->GetDestination();

    if (a->AsSEConstantNode() && b->AsSEConstantNode() &&
        c->AsSEConstantNode() && x->AsSEConstantNode() &&
        y->AsSEConstantNode()) {
      auto constant_a = a->AsSEConstantNode()->FoldToSingleValue();
      auto constant_b = b->AsSEConstantNode()->FoldToSingleValue();
      auto constant_c = c->AsSEConstantNode()->FoldToSingleValue();

      auto constant_x = x->AsSEConstantNode()->FoldToSingleValue();
      auto constant_y = y->AsSEConstantNode()->FoldToSingleValue();

      auto left_hand_side = constant_a * constant_x + constant_b * constant_y;

      if (left_hand_side == constant_c) {
        // Point is on line, return point
        return point_0 ? constraint_0 : constraint_1;
      } else {
        // Point not on line, report independence (empty constraint).
        return make_constraint<DependenceEmpty>();
      }

    } else {
      // Not constants, bail out.
      return make_constraint<DependenceNone>();
    }
  }

  return nullptr;
}

// Propagate constraints function as described in section 5 of Practical
// Dependence Testing, Goff, Kennedy, Tseng, 1991.
SubscriptPair LoopDependenceAnalysis::PropagateConstraints(
    const SubscriptPair& subscript_pair,
    const std::vector<Constraint*>& constraints) {
  SENode* new_first = subscript_pair.first;
  SENode* new_second = subscript_pair.second;

  for (auto& constraint : constraints) {
    // In the paper this is a[k]. We're extracting the coefficient ('a') of a
    // recurrent expression with respect to the loop 'k'.
    SENode* coefficient_of_recurrent =
        scalar_evolution_.GetCoefficientFromRecurrentTerm(
            new_first, constraint->GetLoop());

    // In the paper this is a'[k].
    SENode* coefficient_of_recurrent_prime =
        scalar_evolution_.GetCoefficientFromRecurrentTerm(
            new_second, constraint->GetLoop());

    if (constraint->GetType() == Constraint::Distance) {
      DependenceDistance* as_distance = constraint->AsDependenceDistance();

      // In the paper this is a[k]*d
      SENode* rhs = scalar_evolution_.CreateMultiplyNode(
          coefficient_of_recurrent, as_distance->GetDistance());

      // In the paper this is a[k] <- 0
      SENode* zeroed_coefficient =
          scalar_evolution_.BuildGraphWithoutRecurrentTerm(
              new_first, constraint->GetLoop());

      // In the paper this is e <- e - a[k]*d.
      new_first = scalar_evolution_.CreateSubtraction(zeroed_coefficient, rhs);
      new_first = scalar_evolution_.SimplifyExpression(new_first);

      // In the paper this is a'[k] - a[k].
      SENode* new_child = scalar_evolution_.SimplifyExpression(
          scalar_evolution_.CreateSubtraction(coefficient_of_recurrent_prime,
                                              coefficient_of_recurrent));

      // In the paper this is a'[k]'i[k].
      SERecurrentNode* prime_recurrent =
          scalar_evolution_.GetRecurrentTerm(new_second, constraint->GetLoop());

      if (!prime_recurrent) continue;

      // As we hash the nodes we need to create a new node when we update a
      // child.
      SENode* new_recurrent = scalar_evolution_.CreateRecurrentExpression(
          constraint->GetLoop(), prime_recurrent->GetOffset(), new_child);
      // In the paper this is a'[k] <- a'[k] - a[k].
      new_second = scalar_evolution_.UpdateChildNode(
          new_second, prime_recurrent, new_recurrent);
    }
  }

  new_second = scalar_evolution_.SimplifyExpression(new_second);
  return std::make_pair(new_first, new_second);
}

bool LoopDependenceAnalysis::DeltaTest(
    const std::vector<SubscriptPair>& coupled_subscripts,
    DistanceVector* dv_entry) {
  std::vector<Constraint*> constraints(loops_.size());

  std::vector<bool> loop_appeared(loops_.size());

  std::generate(std::begin(constraints), std::end(constraints),
                [this]() { return make_constraint<DependenceNone>(); });

  // Separate SIV and MIV subscripts
  std::vector<SubscriptPair> siv_subscripts{};
  std::vector<SubscriptPair> miv_subscripts{};

  for (const auto& subscript_pair : coupled_subscripts) {
    if (IsSIV(subscript_pair)) {
      siv_subscripts.push_back(subscript_pair);
    } else {
      miv_subscripts.push_back(subscript_pair);
    }
  }

  // Delta Test
  while (!siv_subscripts.empty()) {
    std::vector<bool> results(siv_subscripts.size());

    std::vector<DistanceVector> current_distances(
        siv_subscripts.size(), DistanceVector(loops_.size()));

    // Apply SIV test to all SIV subscripts, report independence if any of them
    // is independent
    std::transform(
        std::begin(siv_subscripts), std::end(siv_subscripts),
        std::begin(current_distances), std::begin(results),
        [this](SubscriptPair& p, DistanceVector& d) { return SIVTest(p, &d); });

    if (std::accumulate(std::begin(results), std::end(results), false,
                        std::logical_or<bool>{})) {
      return true;
    }

    // Derive new constraint vector.
    std::vector<std::pair<Constraint*, size_t>> all_new_constrants{};

    for (size_t i = 0; i < siv_subscripts.size(); ++i) {
      auto loop = GetLoopForSubscriptPair(siv_subscripts[i]);

      auto loop_id =
          std::distance(std::begin(loops_),
                        std::find(std::begin(loops_), std::end(loops_), loop));

      loop_appeared[loop_id] = true;
      auto distance_entry = current_distances[i].GetEntries()[loop_id];

      if (distance_entry.dependence_information ==
          DistanceEntry::DependenceInformation::DISTANCE) {
        // Construct a DependenceDistance.
        auto node = scalar_evolution_.CreateConstant(distance_entry.distance);

        all_new_constrants.push_back(
            {make_constraint<DependenceDistance>(node, loop), loop_id});
      } else {
        // Construct a DependenceLine.
        const auto& subscript_pair = siv_subscripts[i];
        SENode* source_node = std::get<0>(subscript_pair);
        SENode* destination_node = std::get<1>(subscript_pair);

        int64_t source_induction_count = CountInductionVariables(source_node);
        int64_t destination_induction_count =
            CountInductionVariables(destination_node);

        SENode* a = nullptr;
        SENode* b = nullptr;
        SENode* c = nullptr;

        if (destination_induction_count != 0) {
          a = destination_node->AsSERecurrentNode()->GetCoefficient();
          c = scalar_evolution_.CreateNegation(
              destination_node->AsSERecurrentNode()->GetOffset());
        } else {
          a = scalar_evolution_.CreateConstant(0);
          c = scalar_evolution_.CreateNegation(destination_node);
        }

        if (source_induction_count != 0) {
          b = scalar_evolution_.CreateNegation(
              source_node->AsSERecurrentNode()->GetCoefficient());
          c = scalar_evolution_.CreateAddNode(
              c, source_node->AsSERecurrentNode()->GetOffset());
        } else {
          b = scalar_evolution_.CreateConstant(0);
          c = scalar_evolution_.CreateAddNode(c, source_node);
        }

        a = scalar_evolution_.SimplifyExpression(a);
        b = scalar_evolution_.SimplifyExpression(b);
        c = scalar_evolution_.SimplifyExpression(c);

        all_new_constrants.push_back(
            {make_constraint<DependenceLine>(a, b, c, loop), loop_id});
      }
    }

    // Calculate the intersection between the new and existing constraints.
    std::vector<Constraint*> intersection = constraints;
    for (const auto& constraint_to_intersect : all_new_constrants) {
      auto loop_id = std::get<1>(constraint_to_intersect);
      auto loop = loops_[loop_id];
      intersection[loop_id] = IntersectConstraints(
          intersection[loop_id], std::get<0>(constraint_to_intersect),
          GetLowerBound(loop), GetUpperBound(loop));
    }

    // Report independence if an empty constraint (DependenceEmpty) is found.
    auto first_empty =
        std::find_if(std::begin(intersection), std::end(intersection),
                     [](Constraint* constraint) {
                       return constraint->AsDependenceEmpty() != nullptr;
                     });
    if (first_empty != std::end(intersection)) {
      return true;
    }
    std::vector<SubscriptPair> new_siv_subscripts{};
    std::vector<SubscriptPair> new_miv_subscripts{};

    auto equal =
        std::equal(std::begin(constraints), std::end(constraints),
                   std::begin(intersection),
                   [](Constraint* a, Constraint* b) { return *a == *b; });

    // If any constraints have changed, propagate them into the rest of the
    // subscripts possibly creating new ZIV/SIV subscripts.
    if (!equal) {
      std::vector<SubscriptPair> new_subscripts(miv_subscripts.size());

      // Propagate constraints into MIV subscripts
      std::transform(std::begin(miv_subscripts), std::end(miv_subscripts),
                     std::begin(new_subscripts),
                     [this, &intersection](SubscriptPair& subscript_pair) {
                       return PropagateConstraints(subscript_pair,
                                                   intersection);
                     });

      // If a ZIV subscript is returned, apply test, otherwise, update untested
      // subscripts.
      for (auto& subscript : new_subscripts) {
        if (IsZIV(subscript) && ZIVTest(subscript)) {
          return true;
        } else if (IsSIV(subscript)) {
          new_siv_subscripts.push_back(subscript);
        } else {
          new_miv_subscripts.push_back(subscript);
        }
      }
    }

    // Set new constraints and subscripts to test.
    std::swap(siv_subscripts, new_siv_subscripts);
    std::swap(miv_subscripts, new_miv_subscripts);
    std::swap(constraints, intersection);
  }

  // Create the dependence vector from the constraints.
  for (size_t i = 0; i < loops_.size(); ++i) {
    // Don't touch entries for loops that weren't tested.
    if (loop_appeared[i]) {
      auto current_constraint = constraints[i];
      auto& current_distance_entry = (*dv_entry).GetEntries()[i];

      if (auto dependence_distance =
              current_constraint->AsDependenceDistance()) {
        if (auto constant_node =
                dependence_distance->GetDistance()->AsSEConstantNode()) {
          current_distance_entry.dependence_information =
              DistanceEntry::DependenceInformation::DISTANCE;

          current_distance_entry.distance = constant_node->FoldToSingleValue();
          if (current_distance_entry.distance == 0) {
            current_distance_entry.direction = DistanceEntry::Directions::EQ;
          } else if (current_distance_entry.distance < 0) {
            current_distance_entry.direction = DistanceEntry::Directions::GT;
          } else {
            current_distance_entry.direction = DistanceEntry::Directions::LT;
          }
        }
      } else if (auto dependence_point =
                     current_constraint->AsDependencePoint()) {
        auto source = dependence_point->GetSource();
        auto destination = dependence_point->GetDestination();

        if (source->AsSEConstantNode() && destination->AsSEConstantNode()) {
          current_distance_entry = DistanceEntry(
              source->AsSEConstantNode()->FoldToSingleValue(),
              destination->AsSEConstantNode()->FoldToSingleValue());
        }
      }
    }
  }

  // Test any remaining MIV subscripts and report independence if found.
  std::vector<bool> results(miv_subscripts.size());

  std::transform(std::begin(miv_subscripts), std::end(miv_subscripts),
                 std::begin(results),
                 [this](const SubscriptPair& p) { return GCDMIVTest(p); });

  return std::accumulate(std::begin(results), std::end(results), false,
                         std::logical_or<bool>{});
}

}  // namespace opt
}  // namespace spvtools
