//===--------- SCEVAffinator.cpp  - Create Scops from LLVM IR -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Create a polyhedral description for a SCEV value.
//
//===----------------------------------------------------------------------===//

#include "polly/Support/SCEVAffinator.h"
#include "polly/Options.h"
#include "polly/ScopInfo.h"
#include "polly/Support/GICHelper.h"
#include "polly/Support/SCEVValidator.h"
#include "polly/Support/ScopHelper.h"
#include "isl/aff.h"
#include "isl/local_space.h"
#include "isl/set.h"
#include "isl/val.h"

using namespace llvm;
using namespace polly;

static cl::opt<bool> IgnoreIntegerWrapping(
    "polly-ignore-integer-wrapping",
    cl::desc("Do not build run-time checks to proof absence of integer "
             "wrapping"),
    cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::cat(PollyCategory));

// The maximal number of basic sets we allow during the construction of a
// piecewise affine function. More complex ones will result in very high
// compile time.
static int const MaxDisjunctionsInPwAff = 100;

// The maximal number of bits for which a general expression is modeled
// precisely.
static unsigned const MaxSmallBitWidth = 7;

/// Add the number of basic sets in @p Domain to @p User
static isl_stat addNumBasicSets(__isl_take isl_set *Domain,
                                __isl_take isl_aff *Aff, void *User) {
  auto *NumBasicSets = static_cast<unsigned *>(User);
  *NumBasicSets += isl_set_n_basic_set(Domain);
  isl_set_free(Domain);
  isl_aff_free(Aff);
  return isl_stat_ok;
}

/// Helper to free a PWACtx object.
static void freePWACtx(__isl_take PWACtx &PWAC) {
  isl_pw_aff_free(PWAC.first);
  isl_set_free(PWAC.second);
}

/// Helper to copy a PWACtx object.
static __isl_give PWACtx copyPWACtx(const __isl_keep PWACtx &PWAC) {
  return std::make_pair(isl_pw_aff_copy(PWAC.first), isl_set_copy(PWAC.second));
}

/// Determine if @p PWAC is too complex to continue.
///
/// Note that @p PWAC will be "free" (deallocated) if this function returns
/// true, but not if this function returns false.
static bool isTooComplex(PWACtx &PWAC) {
  unsigned NumBasicSets = 0;
  isl_pw_aff_foreach_piece(PWAC.first, addNumBasicSets, &NumBasicSets);
  if (NumBasicSets <= MaxDisjunctionsInPwAff)
    return false;
  freePWACtx(PWAC);
  return true;
}

/// Return the flag describing the possible wrapping of @p Expr.
static SCEV::NoWrapFlags getNoWrapFlags(const SCEV *Expr) {
  if (auto *NAry = dyn_cast<SCEVNAryExpr>(Expr))
    return NAry->getNoWrapFlags();
  return SCEV::NoWrapMask;
}

static void combine(__isl_keep PWACtx &PWAC0, const __isl_take PWACtx &PWAC1,
                    isl_pw_aff *(Fn)(isl_pw_aff *, isl_pw_aff *)) {
  PWAC0.first = Fn(PWAC0.first, PWAC1.first);
  PWAC0.second = isl_set_union(PWAC0.second, PWAC1.second);
}

static __isl_give isl_pw_aff *getWidthExpValOnDomain(unsigned Width,
                                                     __isl_take isl_set *Dom) {
  auto *Ctx = isl_set_get_ctx(Dom);
  auto *WidthVal = isl_val_int_from_ui(Ctx, Width);
  auto *ExpVal = isl_val_2exp(WidthVal);
  return isl_pw_aff_val_on_domain(Dom, ExpVal);
}

SCEVAffinator::SCEVAffinator(Scop *S, LoopInfo &LI)
    : S(S), Ctx(S->getIslCtx()), SE(*S->getSE()), LI(LI),
      TD(S->getFunction().getParent()->getDataLayout()) {}

SCEVAffinator::~SCEVAffinator() {
  for (auto &CachedPair : CachedExpressions)
    freePWACtx(CachedPair.second);
}

Loop *SCEVAffinator::getScope() { return BB ? LI.getLoopFor(BB) : nullptr; }

void SCEVAffinator::interpretAsUnsigned(__isl_keep PWACtx &PWAC,
                                        unsigned Width) {
  auto *PWA = PWAC.first;
  auto *NonNegDom = isl_pw_aff_nonneg_set(isl_pw_aff_copy(PWA));
  auto *NonNegPWA = isl_pw_aff_intersect_domain(isl_pw_aff_copy(PWA),
                                                isl_set_copy(NonNegDom));
  auto *ExpPWA = getWidthExpValOnDomain(Width, isl_set_complement(NonNegDom));
  PWAC.first = isl_pw_aff_union_add(NonNegPWA, isl_pw_aff_add(PWA, ExpPWA));
}

void SCEVAffinator::takeNonNegativeAssumption(PWACtx &PWAC) {
  auto *NegPWA = isl_pw_aff_neg(isl_pw_aff_copy(PWAC.first));
  auto *NegDom = isl_pw_aff_pos_set(NegPWA);
  PWAC.second = isl_set_union(PWAC.second, isl_set_copy(NegDom));
  auto *Restriction = BB ? NegDom : isl_set_params(NegDom);
  auto DL = BB ? BB->getTerminator()->getDebugLoc() : DebugLoc();
  S->recordAssumption(UNSIGNED, Restriction, DL, AS_RESTRICTION, BB);
}

__isl_give PWACtx SCEVAffinator::getPWACtxFromPWA(__isl_take isl_pw_aff *PWA) {
  return std::make_pair(
      PWA, isl_set_empty(isl_space_set_alloc(Ctx, 0, NumIterators)));
}

__isl_give PWACtx SCEVAffinator::getPwAff(const SCEV *Expr, BasicBlock *BB) {
  this->BB = BB;

  if (BB) {
    auto *DC = S->getDomainConditions(BB);
    NumIterators = isl_set_n_dim(DC);
    isl_set_free(DC);
  } else
    NumIterators = 0;

  return visit(Expr);
}

__isl_give PWACtx SCEVAffinator::checkForWrapping(const SCEV *Expr,
                                                  PWACtx PWAC) const {
  // If the SCEV flags do contain NSW (no signed wrap) then PWA already
  // represents Expr in modulo semantic (it is not allowed to overflow), thus we
  // are done. Otherwise, we will compute:
  //   PWA = ((PWA + 2^(n-1)) mod (2 ^ n)) - 2^(n-1)
  // whereas n is the number of bits of the Expr, hence:
  //   n = bitwidth(ExprType)

  if (IgnoreIntegerWrapping || (getNoWrapFlags(Expr) & SCEV::FlagNSW))
    return PWAC;

  auto *PWA = PWAC.first;
  auto *PWAMod = addModuloSemantic(isl_pw_aff_copy(PWA), Expr->getType());
  auto *NotEqualSet = isl_pw_aff_ne_set(isl_pw_aff_copy(PWA), PWAMod);
  PWAC.second = isl_set_union(PWAC.second, isl_set_copy(NotEqualSet));
  PWAC.second = isl_set_coalesce(PWAC.second);

  const DebugLoc &Loc = BB ? BB->getTerminator()->getDebugLoc() : DebugLoc();
  NotEqualSet = BB ? NotEqualSet : isl_set_params(NotEqualSet);
  NotEqualSet = isl_set_coalesce(NotEqualSet);

  if (isl_set_is_empty(NotEqualSet))
    isl_set_free(NotEqualSet);
  else
    S->recordAssumption(WRAPPING, NotEqualSet, Loc, AS_RESTRICTION, BB);

  return PWAC;
}

__isl_give isl_pw_aff *
SCEVAffinator::addModuloSemantic(__isl_take isl_pw_aff *PWA,
                                 Type *ExprType) const {
  unsigned Width = TD.getTypeSizeInBits(ExprType);
  isl_ctx *Ctx = isl_pw_aff_get_ctx(PWA);

  isl_val *ModVal = isl_val_int_from_ui(Ctx, Width);
  ModVal = isl_val_2exp(ModVal);

  isl_set *Domain = isl_pw_aff_domain(isl_pw_aff_copy(PWA));
  isl_pw_aff *AddPW = getWidthExpValOnDomain(Width - 1, Domain);

  PWA = isl_pw_aff_add(PWA, isl_pw_aff_copy(AddPW));
  PWA = isl_pw_aff_mod_val(PWA, ModVal);
  PWA = isl_pw_aff_sub(PWA, AddPW);

  return PWA;
}

bool SCEVAffinator::hasNSWAddRecForLoop(Loop *L) const {
  for (const auto &CachedPair : CachedExpressions) {
    auto *AddRec = dyn_cast<SCEVAddRecExpr>(CachedPair.first.first);
    if (!AddRec)
      continue;
    if (AddRec->getLoop() != L)
      continue;
    if (AddRec->getNoWrapFlags() & SCEV::FlagNSW)
      return true;
  }

  return false;
}

bool SCEVAffinator::computeModuloForExpr(const SCEV *Expr) {
  unsigned Width = TD.getTypeSizeInBits(Expr->getType());
  // We assume nsw expressions never overflow.
  if (auto *NAry = dyn_cast<SCEVNAryExpr>(Expr))
    if (NAry->getNoWrapFlags() & SCEV::FlagNSW)
      return false;
  return Width <= MaxSmallBitWidth;
}

__isl_give PWACtx SCEVAffinator::visit(const SCEV *Expr) {

  auto Key = std::make_pair(Expr, BB);
  PWACtx PWAC = CachedExpressions[Key];
  if (PWAC.first)
    return copyPWACtx(PWAC);

  auto ConstantAndLeftOverPair = extractConstantFactor(Expr, SE);
  auto *Factor = ConstantAndLeftOverPair.first;
  Expr = ConstantAndLeftOverPair.second;

  auto *Scope = getScope();
  S->addParams(getParamsInAffineExpr(&S->getRegion(), Scope, Expr, SE));

  // In case the scev is a valid parameter, we do not further analyze this
  // expression, but create a new parameter in the isl_pw_aff. This allows us
  // to treat subexpressions that we cannot translate into an piecewise affine
  // expression, as constant parameters of the piecewise affine expression.
  if (isl_id *Id = S->getIdForParam(Expr)) {
    isl_space *Space = isl_space_set_alloc(Ctx, 1, NumIterators);
    Space = isl_space_set_dim_id(Space, isl_dim_param, 0, Id);

    isl_set *Domain = isl_set_universe(isl_space_copy(Space));
    isl_aff *Affine = isl_aff_zero_on_domain(isl_local_space_from_space(Space));
    Affine = isl_aff_add_coefficient_si(Affine, isl_dim_param, 0, 1);

    PWAC = getPWACtxFromPWA(isl_pw_aff_alloc(Domain, Affine));
  } else {
    PWAC = SCEVVisitor<SCEVAffinator, PWACtx>::visit(Expr);
    if (computeModuloForExpr(Expr))
      PWAC.first = addModuloSemantic(PWAC.first, Expr->getType());
    else
      PWAC = checkForWrapping(Expr, PWAC);
  }

  if (!Factor->getType()->isIntegerTy(1)) {
    combine(PWAC, visitConstant(Factor), isl_pw_aff_mul);
    if (computeModuloForExpr(Key.first))
      PWAC.first = addModuloSemantic(PWAC.first, Expr->getType());
  }

  // For compile time reasons we need to simplify the PWAC before we cache and
  // return it.
  PWAC.first = isl_pw_aff_coalesce(PWAC.first);
  if (!computeModuloForExpr(Key.first))
    PWAC = checkForWrapping(Key.first, PWAC);

  CachedExpressions[Key] = copyPWACtx(PWAC);
  return PWAC;
}

__isl_give PWACtx SCEVAffinator::visitConstant(const SCEVConstant *Expr) {
  ConstantInt *Value = Expr->getValue();
  isl_val *v;

  // LLVM does not define if an integer value is interpreted as a signed or
  // unsigned value. Hence, without further information, it is unknown how
  // this value needs to be converted to GMP. At the moment, we only support
  // signed operations. So we just interpret it as signed. Later, there are
  // two options:
  //
  // 1. We always interpret any value as signed and convert the values on
  //    demand.
  // 2. We pass down the signedness of the calculation and use it to interpret
  //    this constant correctly.
  v = isl_valFromAPInt(Ctx, Value->getValue(), /* isSigned */ true);

  isl_space *Space = isl_space_set_alloc(Ctx, 0, NumIterators);
  isl_local_space *ls = isl_local_space_from_space(Space);
  return getPWACtxFromPWA(isl_pw_aff_from_aff(isl_aff_val_on_domain(ls, v)));
}

__isl_give PWACtx
SCEVAffinator::visitTruncateExpr(const SCEVTruncateExpr *Expr) {
  // Truncate operations are basically modulo operations, thus we can
  // model them that way. However, for large types we assume the operand
  // to fit in the new type size instead of introducing a modulo with a very
  // large constant.

  auto *Op = Expr->getOperand();
  auto OpPWAC = visit(Op);

  unsigned Width = TD.getTypeSizeInBits(Expr->getType());

  if (computeModuloForExpr(Expr))
    return OpPWAC;

  auto *Dom = isl_pw_aff_domain(isl_pw_aff_copy(OpPWAC.first));
  auto *ExpPWA = getWidthExpValOnDomain(Width - 1, Dom);
  auto *GreaterDom =
      isl_pw_aff_ge_set(isl_pw_aff_copy(OpPWAC.first), isl_pw_aff_copy(ExpPWA));
  auto *SmallerDom =
      isl_pw_aff_lt_set(isl_pw_aff_copy(OpPWAC.first), isl_pw_aff_neg(ExpPWA));
  auto *OutOfBoundsDom = isl_set_union(SmallerDom, GreaterDom);
  OpPWAC.second = isl_set_union(OpPWAC.second, isl_set_copy(OutOfBoundsDom));

  if (!BB) {
    assert(isl_set_dim(OutOfBoundsDom, isl_dim_set) == 0 &&
           "Expected a zero dimensional set for non-basic-block domains");
    OutOfBoundsDom = isl_set_params(OutOfBoundsDom);
  }

  S->recordAssumption(UNSIGNED, OutOfBoundsDom, DebugLoc(), AS_RESTRICTION, BB);

  return OpPWAC;
}

__isl_give PWACtx
SCEVAffinator::visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
  // A zero-extended value can be interpreted as a piecewise defined signed
  // value. If the value was non-negative it stays the same, otherwise it
  // is the sum of the original value and 2^n where n is the bit-width of
  // the original (or operand) type. Examples:
  //   zext i8 127 to i32 -> { [127] }
  //   zext i8  -1 to i32 -> { [256 + (-1)] } = { [255] }
  //   zext i8  %v to i32 -> [v] -> { [v] | v >= 0; [256 + v] | v < 0 }
  //
  // However, LLVM/Scalar Evolution uses zero-extend (potentially lead by a
  // truncate) to represent some forms of modulo computation. The left-hand side
  // of the condition in the code below would result in the SCEV
  // "zext i1 <false, +, true>for.body" which is just another description
  // of the C expression "i & 1 != 0" or, equivalently, "i % 2 != 0".
  //
  //   for (i = 0; i < N; i++)
  //     if (i & 1 != 0 /* == i % 2 */)
  //       /* do something */
  //
  // If we do not make the modulo explicit but only use the mechanism described
  // above we will get the very restrictive assumption "N < 3", because for all
  // values of N >= 3 the SCEVAddRecExpr operand of the zero-extend would wrap.
  // Alternatively, we can make the modulo in the operand explicit in the
  // resulting piecewise function and thereby avoid the assumption on N. For the
  // example this would result in the following piecewise affine function:
  // { [i0] -> [(1)] : 2*floor((-1 + i0)/2) = -1 + i0;
  //   [i0] -> [(0)] : 2*floor((i0)/2) = i0 }
  // To this end we can first determine if the (immediate) operand of the
  // zero-extend can wrap and, in case it might, we will use explicit modulo
  // semantic to compute the result instead of emitting non-wrapping
  // assumptions.
  //
  // Note that operands with large bit-widths are less likely to be negative
  // because it would result in a very large access offset or loop bound after
  // the zero-extend. To this end one can optimistically assume the operand to
  // be positive and avoid the piecewise definition if the bit-width is bigger
  // than some threshold (here MaxZextSmallBitWidth).
  //
  // We choose to go with a hybrid solution of all modeling techniques described
  // above. For small bit-widths (up to MaxZextSmallBitWidth) we will model the
  // wrapping explicitly and use a piecewise defined function. However, if the
  // bit-width is bigger than MaxZextSmallBitWidth we will employ overflow
  // assumptions and assume the "former negative" piece will not exist.

  auto *Op = Expr->getOperand();
  auto OpPWAC = visit(Op);

  // If the width is to big we assume the negative part does not occur.
  if (!computeModuloForExpr(Op)) {
    takeNonNegativeAssumption(OpPWAC);
    return OpPWAC;
  }

  // If the width is small build the piece for the non-negative part and
  // the one for the negative part and unify them.
  unsigned Width = TD.getTypeSizeInBits(Op->getType());
  interpretAsUnsigned(OpPWAC, Width);
  return OpPWAC;
}

__isl_give PWACtx
SCEVAffinator::visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
  // As all values are represented as signed, a sign extension is a noop.
  return visit(Expr->getOperand());
}

__isl_give PWACtx SCEVAffinator::visitAddExpr(const SCEVAddExpr *Expr) {
  PWACtx Sum = visit(Expr->getOperand(0));

  for (int i = 1, e = Expr->getNumOperands(); i < e; ++i) {
    combine(Sum, visit(Expr->getOperand(i)), isl_pw_aff_add);
    if (isTooComplex(Sum))
      return std::make_pair(nullptr, nullptr);
  }

  return Sum;
}

__isl_give PWACtx SCEVAffinator::visitMulExpr(const SCEVMulExpr *Expr) {
  PWACtx Prod = visit(Expr->getOperand(0));

  for (int i = 1, e = Expr->getNumOperands(); i < e; ++i) {
    combine(Prod, visit(Expr->getOperand(i)), isl_pw_aff_mul);
    if (isTooComplex(Prod))
      return std::make_pair(nullptr, nullptr);
  }

  return Prod;
}

__isl_give PWACtx SCEVAffinator::visitAddRecExpr(const SCEVAddRecExpr *Expr) {
  assert(Expr->isAffine() && "Only affine AddRecurrences allowed");

  auto Flags = Expr->getNoWrapFlags();

  // Directly generate isl_pw_aff for Expr if 'start' is zero.
  if (Expr->getStart()->isZero()) {
    assert(S->contains(Expr->getLoop()) &&
           "Scop does not contain the loop referenced in this AddRec");

    PWACtx Step = visit(Expr->getOperand(1));
    isl_space *Space = isl_space_set_alloc(Ctx, 0, NumIterators);
    isl_local_space *LocalSpace = isl_local_space_from_space(Space);

    unsigned loopDimension = S->getRelativeLoopDepth(Expr->getLoop());

    isl_aff *LAff = isl_aff_set_coefficient_si(
        isl_aff_zero_on_domain(LocalSpace), isl_dim_in, loopDimension, 1);
    isl_pw_aff *LPwAff = isl_pw_aff_from_aff(LAff);

    Step.first = isl_pw_aff_mul(Step.first, LPwAff);
    return Step;
  }

  // Translate AddRecExpr from '{start, +, inc}' into 'start + {0, +, inc}'
  // if 'start' is not zero.
  // TODO: Using the original SCEV no-wrap flags is not always safe, however
  //       as our code generation is reordering the expression anyway it doesn't
  //       really matter.
  const SCEV *ZeroStartExpr =
      SE.getAddRecExpr(SE.getConstant(Expr->getStart()->getType(), 0),
                       Expr->getStepRecurrence(SE), Expr->getLoop(), Flags);

  PWACtx Result = visit(ZeroStartExpr);
  PWACtx Start = visit(Expr->getStart());
  combine(Result, Start, isl_pw_aff_add);
  return Result;
}

__isl_give PWACtx SCEVAffinator::visitSMaxExpr(const SCEVSMaxExpr *Expr) {
  PWACtx Max = visit(Expr->getOperand(0));

  for (int i = 1, e = Expr->getNumOperands(); i < e; ++i) {
    combine(Max, visit(Expr->getOperand(i)), isl_pw_aff_max);
    if (isTooComplex(Max))
      return std::make_pair(nullptr, nullptr);
  }

  return Max;
}

__isl_give PWACtx SCEVAffinator::visitUMaxExpr(const SCEVUMaxExpr *Expr) {
  llvm_unreachable("SCEVUMaxExpr not yet supported");
}

__isl_give PWACtx SCEVAffinator::visitUDivExpr(const SCEVUDivExpr *Expr) {
  // The handling of unsigned division is basically the same as for signed
  // division, except the interpretation of the operands. As the divisor
  // has to be constant in both cases we can simply interpret it as an
  // unsigned value without additional complexity in the representation.
  // For the dividend we could choose from the different representation
  // schemes introduced for zero-extend operations but for now we will
  // simply use an assumption.
  auto *Dividend = Expr->getLHS();
  auto *Divisor = Expr->getRHS();
  assert(isa<SCEVConstant>(Divisor) &&
         "UDiv is no parameter but has a non-constant RHS.");

  auto DividendPWAC = visit(Dividend);
  auto DivisorPWAC = visit(Divisor);

  if (SE.isKnownNegative(Divisor)) {
    // Interpret negative divisors unsigned. This is a special case of the
    // piece-wise defined value described for zero-extends as we already know
    // the actual value of the constant divisor.
    unsigned Width = TD.getTypeSizeInBits(Expr->getType());
    auto *DivisorDom = isl_pw_aff_domain(isl_pw_aff_copy(DivisorPWAC.first));
    auto *WidthExpPWA = getWidthExpValOnDomain(Width, DivisorDom);
    DivisorPWAC.first = isl_pw_aff_add(DivisorPWAC.first, WidthExpPWA);
  }

  // TODO: One can represent the dividend as piece-wise function to be more
  //       precise but therefor a heuristic is needed.

  // Assume a non-negative dividend.
  takeNonNegativeAssumption(DividendPWAC);

  combine(DividendPWAC, DivisorPWAC, isl_pw_aff_div);
  DividendPWAC.first = isl_pw_aff_floor(DividendPWAC.first);

  return DividendPWAC;
}

__isl_give PWACtx SCEVAffinator::visitSDivInstruction(Instruction *SDiv) {
  assert(SDiv->getOpcode() == Instruction::SDiv && "Assumed SDiv instruction!");

  auto *Scope = getScope();
  auto *Divisor = SDiv->getOperand(1);
  auto *DivisorSCEV = SE.getSCEVAtScope(Divisor, Scope);
  auto DivisorPWAC = visit(DivisorSCEV);
  assert(isa<SCEVConstant>(DivisorSCEV) &&
         "SDiv is no parameter but has a non-constant RHS.");

  auto *Dividend = SDiv->getOperand(0);
  auto *DividendSCEV = SE.getSCEVAtScope(Dividend, Scope);
  auto DividendPWAC = visit(DividendSCEV);
  combine(DividendPWAC, DivisorPWAC, isl_pw_aff_tdiv_q);
  return DividendPWAC;
}

__isl_give PWACtx SCEVAffinator::visitSRemInstruction(Instruction *SRem) {
  assert(SRem->getOpcode() == Instruction::SRem && "Assumed SRem instruction!");

  auto *Scope = getScope();
  auto *Divisor = SRem->getOperand(1);
  auto *DivisorSCEV = SE.getSCEVAtScope(Divisor, Scope);
  auto DivisorPWAC = visit(DivisorSCEV);
  assert(isa<ConstantInt>(Divisor) &&
         "SRem is no parameter but has a non-constant RHS.");

  auto *Dividend = SRem->getOperand(0);
  auto *DividendSCEV = SE.getSCEVAtScope(Dividend, Scope);
  auto DividendPWAC = visit(DividendSCEV);
  combine(DividendPWAC, DivisorPWAC, isl_pw_aff_tdiv_r);
  return DividendPWAC;
}

__isl_give PWACtx SCEVAffinator::visitUnknown(const SCEVUnknown *Expr) {
  if (Instruction *I = dyn_cast<Instruction>(Expr->getValue())) {
    switch (I->getOpcode()) {
    case Instruction::IntToPtr:
      return visit(SE.getSCEVAtScope(I->getOperand(0), getScope()));
    case Instruction::PtrToInt:
      return visit(SE.getSCEVAtScope(I->getOperand(0), getScope()));
    case Instruction::SDiv:
      return visitSDivInstruction(I);
    case Instruction::SRem:
      return visitSRemInstruction(I);
    default:
      break; // Fall through.
    }
  }

  llvm_unreachable(
      "Unknowns SCEV was neither parameter nor a valid instruction.");
}
