//===--------- 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;
}

/// Determine if @p PWAC is too complex to continue.
static bool isTooComplex(PWACtx PWAC) {
  unsigned NumBasicSets = 0;
  isl_pw_aff_foreach_piece(PWAC.first.get(), addNumBasicSets, &NumBasicSets);
  if (NumBasicSets <= MaxDisjunctionsInPwAff)
    return false;
  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 PWACtx combine(PWACtx PWAC0, PWACtx PWAC1,
                      __isl_give isl_pw_aff *(Fn)(__isl_take isl_pw_aff *,
                                                  __isl_take isl_pw_aff *)) {
  PWAC0.first = isl::manage(Fn(PWAC0.first.release(), PWAC1.first.release()));
  PWAC0.second = PWAC0.second.unite(PWAC1.second);
  return PWAC0;
}

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().get()), SE(*S->getSE()), LI(LI),
      TD(S->getFunction().getParent()->getDataLayout()) {}

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

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

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

PWACtx SCEVAffinator::getPWACtxFromPWA(isl::pw_aff PWA) {
  return std::make_pair(PWA, isl::set::empty(isl::space(Ctx, 0, NumIterators)));
}

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

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

  return visit(Expr);
}

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;

  isl::pw_aff PWAMod = addModuloSemantic(PWAC.first, Expr->getType());

  isl::set NotEqualSet = PWAC.first.ne_set(PWAMod);
  PWAC.second = PWAC.second.unite(NotEqualSet).coalesce();

  const DebugLoc &Loc = BB ? BB->getTerminator()->getDebugLoc() : DebugLoc();
  if (!BB)
    NotEqualSet = NotEqualSet.params();
  NotEqualSet = NotEqualSet.coalesce();

  if (!NotEqualSet.is_empty())
    S->recordAssumption(WRAPPING, NotEqualSet, Loc, AS_RESTRICTION, BB);

  return PWAC;
}

isl::pw_aff SCEVAffinator::addModuloSemantic(isl::pw_aff PWA,
                                             Type *ExprType) const {
  unsigned Width = TD.getTypeSizeInBits(ExprType);

  auto ModVal = isl::val::int_from_ui(Ctx, Width);
  ModVal = ModVal.two_exp();

  isl::set Domain = PWA.domain();
  isl::pw_aff AddPW =
      isl::manage(getWidthExpValOnDomain(Width - 1, Domain.release()));

  return PWA.add(AddPW).mod(ModVal).sub(AddPW);
}

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;
}

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

  auto Key = std::make_pair(Expr, BB);
  PWACtx PWAC = CachedExpressions[Key];
  if (PWAC.first)
    return 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).release()) {
    isl_space *Space = isl_space_set_alloc(Ctx.get(), 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::manage(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)) {
    PWAC = 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 = PWAC.first.coalesce();
  if (!computeModuloForExpr(Key.first))
    PWAC = checkForWrapping(Key.first, PWAC);

  CachedExpressions[Key] = PWAC;
  return PWAC;
}

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.get(), Value->getValue(), /* isSigned */ true);

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

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 = OpPWAC.first.domain().release();
  auto *ExpPWA = getWidthExpValOnDomain(Width - 1, Dom);
  auto *GreaterDom =
      isl_pw_aff_ge_set(OpPWAC.first.copy(), isl_pw_aff_copy(ExpPWA));
  auto *SmallerDom =
      isl_pw_aff_lt_set(OpPWAC.first.copy(), isl_pw_aff_neg(ExpPWA));
  auto *OutOfBoundsDom = isl_set_union(SmallerDom, GreaterDom);
  OpPWAC.second = OpPWAC.second.unite(isl::manage_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, isl::manage(OutOfBoundsDom), DebugLoc(),
                      AS_RESTRICTION, BB);

  return OpPWAC;
}

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;
}

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

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

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

  return Sum;
}

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

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

  return Prod;
}

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.get(), 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 = Step.first.mul(isl::manage(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());
  Result = combine(Result, Start, isl_pw_aff_add);
  return Result;
}

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

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

  return Max;
}

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

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 = DivisorPWAC.first.domain().release();
    auto *WidthExpPWA = getWidthExpValOnDomain(Width, DivisorDom);
    DivisorPWAC.first = DivisorPWAC.first.add(isl::manage(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);

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

  return DividendPWAC;
}

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);
  DividendPWAC = combine(DividendPWAC, DivisorPWAC, isl_pw_aff_tdiv_q);
  return DividendPWAC;
}

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);
  DividendPWAC = combine(DividendPWAC, DivisorPWAC, isl_pw_aff_tdiv_r);
  return DividendPWAC;
}

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.");
}

PWACtx SCEVAffinator::complexityBailout() {
  // We hit the complexity limit for affine expressions; invalidate the scop
  // and return a constant zero.
  const DebugLoc &Loc = BB ? BB->getTerminator()->getDebugLoc() : DebugLoc();
  S->invalidate(COMPLEXITY, Loc);
  return visit(SE.getZero(Type::getInt32Ty(S->getFunction().getContext())));
}
