class ValidatorResult visitMulExpr(const SCEVMulExpr *Expr) { ValidatorResult Return(SCEVType::INT); bool HasMultipleParams = false; for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) { ValidatorResult Op = visit(Expr->getOperand(i)); if (Op.isINT()) continue; if (Op.isPARAM() && Return.isPARAM()) { HasMultipleParams = true; continue; } if ((Op.isIV() || Op.isPARAM()) && !Return.isINT()) { DEBUG(dbgs() << "INVALID: More than one non-int operand in MulExpr\n" << "\tExpr: " << *Expr << "\n" << "\tPrevious expression type: " << Return << "\n" << "\tNext operand (" << Op << "): " << *Expr->getOperand(i) << "\n"); return ValidatorResult(SCEVType::INVALID); } Return.merge(Op); } if (HasMultipleParams) return ValidatorResult(SCEVType::PARAM, Expr); // TODO: Check for NSW and NUW. return Return; }
std::vector<const SCEV *> getParamsInAffineExpr(const Region *R, const SCEV *Expr, ScalarEvolution &SE, const Value *BaseAddress) { if (isa<SCEVCouldNotCompute>(Expr)) return std::vector<const SCEV *>(); SCEVValidator Validator(R, SE, BaseAddress); ValidatorResult Result = Validator.visit(Expr); return Result.getParameters(); }
class ValidatorResult visitUDivExpr(const SCEVUDivExpr *Expr) { ValidatorResult LHS = visit(Expr->getLHS()); ValidatorResult RHS = visit(Expr->getRHS()); // We currently do not represent an unsigned division as an affine // expression. If the division is constant during Scop execution we treat it // as a parameter, otherwise we bail out. if (LHS.isConstant() && RHS.isConstant()) return ValidatorResult(SCEVType::PARAM, Expr); DEBUG(dbgs() << "INVALID: unsigned division of non-constant expressions"); return ValidatorResult(SCEVType::INVALID); }
class ValidatorResult visitUMaxExpr(const SCEVUMaxExpr *Expr) { // We do not support unsigned operations. If 'Expr' is constant during Scop // execution we treat this as a parameter, otherwise we bail out. for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) { ValidatorResult Op = visit(Expr->getOperand(i)); if (!Op.isConstant()) { DEBUG(dbgs() << "INVALID: UMaxExpr has a non-constant operand"); return ValidatorResult(SCEVType::INVALID); } } return ValidatorResult(SCEVType::PARAM, Expr); }
class ValidatorResult visitSMaxExpr(const SCEVSMaxExpr *Expr) { ValidatorResult Return(SCEVType::INT, Expr); for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) { ValidatorResult Op = visit(Expr->getOperand(i)); if (!Op.isValid()) return Op; Return.merge(Op); } return Return; }
class ValidatorResult visitAddRecExpr(const SCEVAddRecExpr *Expr) { if (!Expr->isAffine()) { DEBUG(dbgs() << "INVALID: AddRec is not affine"); return ValidatorResult(SCEVType::INVALID); } ValidatorResult Start = visit(Expr->getStart()); ValidatorResult Recurrence = visit(Expr->getStepRecurrence(SE)); if (!Start.isValid()) return Start; if (!Recurrence.isValid()) return Recurrence; auto *L = Expr->getLoop(); if (R->contains(L) && (!Scope || !L->contains(Scope))) { DEBUG(dbgs() << "INVALID: AddRec out of a loop whose exit value is not " "synthesizable"); return ValidatorResult(SCEVType::INVALID); } if (R->contains(L)) { if (Recurrence.isINT()) { ValidatorResult Result(SCEVType::IV); Result.addParamsFrom(Start); return Result; } DEBUG(dbgs() << "INVALID: AddRec within scop has non-int" "recurrence part"); return ValidatorResult(SCEVType::INVALID); } assert(Start.isConstant() && Recurrence.isConstant() && "Expected 'Start' and 'Recurrence' to be constant"); // Directly generate ValidatorResult for Expr if 'start' is zero. if (Expr->getStart()->isZero()) return ValidatorResult(SCEVType::PARAM, Expr); // Translate AddRecExpr from '{start, +, inc}' into 'start + {0, +, inc}' // if 'start' is not zero. const SCEV *ZeroStartExpr = SE.getAddRecExpr( SE.getConstant(Expr->getStart()->getType(), 0), Expr->getStepRecurrence(SE), Expr->getLoop(), Expr->getNoWrapFlags()); ValidatorResult ZeroStartResult = ValidatorResult(SCEVType::PARAM, ZeroStartExpr); ZeroStartResult.addParamsFrom(Start); return ZeroStartResult; }
class ValidatorResult visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) { ValidatorResult Op = visit(Expr->getOperand()); switch (Op.getType()) { case SCEVType::INT: case SCEVType::PARAM: // We currently do not represent a truncate expression as an affine // expression. If it is constant during Scop execution, we treat it as a // parameter. return ValidatorResult(SCEVType::PARAM, Expr); case SCEVType::IV: DEBUG(dbgs() << "INVALID: ZeroExtend of SCEVType::IV expression"); return ValidatorResult(SCEVType::INVALID); case SCEVType::INVALID: return Op; } llvm_unreachable("Unknown SCEVType"); }