// 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 opt::Instruction* source,
                                           const opt::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);

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

  auto num_access_chains =
      (source_access_chain->opcode() == SpvOpAccessChain) +
      (destination_access_chain->opcode() == SpvOpAccessChain);

  // If neither is an access chain, then they are load/store to a variable.
  if (num_access_chains == 0) {
    if (source_access_chain != destination_access_chain) {
      // Not the same location, report independence
      return true;
    } else {
      // Accessing the same variable
      for (auto& entry : distance_vector->GetEntries()) {
        entry = DistanceEntry();
      }
      return false;
    }
  }

  // If only one is an access chain, it could be accessing a part of a struct
  if (num_access_chains == 1) {
    auto source_is_chain = source_access_chain->opcode() == SpvOpAccessChain;
    auto access_chain =
        source_is_chain ? source_access_chain : destination_access_chain;
    auto variable =
        source_is_chain ? destination_access_chain : source_access_chain;

    auto location_in_chain = GetOperandDefinition(access_chain, 0);

    if (variable != location_in_chain) {
      // Not the same location, report independence
      return true;
    } else {
      // Accessing the same variable
      for (auto& entry : distance_vector->GetEntries()) {
        entry = DistanceEntry();
      }
      return false;
    }
  }

  // If the access chains aren't collecting from the same structure there is no
  // dependence.
  opt::Instruction* source_array = GetOperandDefinition(source_access_chain, 0);
  opt::Instruction* destination_array =
      GetOperandDefinition(destination_access_chain, 0);

  // Nested access chains are not supported yet, bail out.
  if (source_array->opcode() == SpvOpAccessChain ||
      destination_array->opcode() == SpvOpAccessChain) {
    for (auto& entry : distance_vector->GetEntries()) {
      entry = DistanceEntry();
    }
    return false;
  }

  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<opt::Instruction*> source_subscripts = GetSubscripts(source);
  std::vector<opt::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<opt::Instruction*, opt::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 opt::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 opt::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 opt::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 opt::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 opt::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 opt::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<opt::Instruction*, opt::Instruction*>>>;
PartitionedSubscripts LoopDependenceAnalysis::PartitionSubscripts(
    const std::vector<opt::Instruction*>& source_subscripts,
    const std::vector<opt::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<opt::Instruction*, opt::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<opt::Instruction*, opt::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
