[NFC] [DA] Refactoring getIndexExpressionsFromGEP

Summary:
This patch moves the getIndexExpressionsFromGEP function from polly
into ScalarEvolution so that both polly and DependenceAnalysis can
use it for the purpose of subscript delinearization when the array
sizes are not parametric.

Authored By: bmahjour

Reviewer: Meinersbur, sebpop, fhahn, dmgreen, grosser, etiotto, bollu

Reviewed By: Meinersbur

Subscribers: hiraditya, arphaman, Whitney, ppc-slack, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D73995
This commit is contained in:
Bardia Mahjour 2020-02-24 17:28:03 -05:00
parent c93112dc4f
commit cf9dae122e
5 changed files with 61 additions and 68 deletions

View File

@ -998,6 +998,19 @@ public:
SmallVectorImpl<const SCEV *> &Subscripts,
SmallVectorImpl<const SCEV *> &Sizes);
/// Gathers the individual index expressions from a GEP instruction.
///
/// This function optimistically assumes the GEP references into a fixed size
/// array. If this is actually true, this function returns a list of array
/// subscript expressions in \p Subscripts and a list of integers describing
/// the size of the individual array dimensions in \p Sizes. Both lists have
/// either equal length or the size list is one element shorter in case there
/// is no known size available for the outermost array dimension. Returns true
/// if successful and false otherwise.
bool getIndexExpressionsFromGEP(const GetElementPtrInst *GEP,
SmallVectorImpl<const SCEV *> &Subscripts,
SmallVectorImpl<int> &Sizes);
/// Split this SCEVAddRecExpr into two vectors of SCEVs representing the
/// subscripts and sizes of an array access.
///

View File

@ -11409,6 +11409,51 @@ void ScalarEvolution::delinearize(const SCEV *Expr,
});
}
bool ScalarEvolution::getIndexExpressionsFromGEP(
const GetElementPtrInst *GEP, SmallVectorImpl<const SCEV *> &Subscripts,
SmallVectorImpl<int> &Sizes) {
assert(Subscripts.empty() && Sizes.empty() &&
"Expected output lists to be empty on entry to this function.");
assert(GEP && "getIndexExpressionsFromGEP called with a null GEP");
Type *Ty = GEP->getPointerOperandType();
bool DroppedFirstDim = false;
for (unsigned i = 1; i < GEP->getNumOperands(); i++) {
const SCEV *Expr = getSCEV(GEP->getOperand(i));
if (i == 1) {
if (auto *PtrTy = dyn_cast<PointerType>(Ty)) {
Ty = PtrTy->getElementType();
} else if (auto *ArrayTy = dyn_cast<ArrayType>(Ty)) {
Ty = ArrayTy->getElementType();
} else {
Subscripts.clear();
Sizes.clear();
return false;
}
if (auto *Const = dyn_cast<SCEVConstant>(Expr))
if (Const->getValue()->isZero()) {
DroppedFirstDim = true;
continue;
}
Subscripts.push_back(Expr);
continue;
}
auto *ArrayTy = dyn_cast<ArrayType>(Ty);
if (!ArrayTy) {
Subscripts.clear();
Sizes.clear();
return false;
}
Subscripts.push_back(Expr);
if (!(DroppedFirstDim && i == 2))
Sizes.push_back(ArrayTy->getNumElements());
Ty = ArrayTy->getElementType();
}
return !Subscripts.empty();
}
//===----------------------------------------------------------------------===//
// SCEVCallbackVH Class Implementation
//===----------------------------------------------------------------------===//

View File

@ -502,22 +502,6 @@ bool canSynthesize(const llvm::Value *V, const Scop &S,
/// case this function returns nullptr.
llvm::BasicBlock *getUseBlock(const llvm::Use &U);
/// Derive the individual index expressions from a GEP instruction.
///
/// This function optimistically assumes the GEP references into a fixed size
/// array. If this is actually true, this function returns a list of array
/// subscript expressions as SCEV as well as a list of integers describing
/// the size of the individual array dimensions. Both lists have either equal
/// length or the size list is one element shorter in case there is no known
/// size available for the outermost array dimension.
///
/// @param GEP The GetElementPtr instruction to analyze.
///
/// @return A tuple with the subscript expressions and the dimension sizes.
std::tuple<std::vector<const llvm::SCEV *>, std::vector<int>>
getIndexExpressionsFromGEP(llvm::GetElementPtrInst *GEP,
llvm::ScalarEvolution &SE);
// If the loop is nonaffine/boxed, return the first non-boxed surrounding loop
// for Polly. If the loop is affine, return the loop itself.
//

View File

@ -1629,9 +1629,9 @@ bool ScopBuilder::buildAccessMultiDimFixed(MemAccInst Inst, ScopStmt *Stmt) {
if (!GEP)
return false;
std::vector<const SCEV *> Subscripts;
std::vector<int> Sizes;
std::tie(Subscripts, Sizes) = getIndexExpressionsFromGEP(GEP, SE);
SmallVector<const SCEV *, 4> Subscripts;
SmallVector<int, 4> Sizes;
SE.getIndexExpressionsFromGEP(GEP, Subscripts, Sizes);
auto *BasePtr = GEP->getOperand(0);
if (auto *BasePtrCast = dyn_cast<BitCastInst>(BasePtr))

View File

@ -668,55 +668,6 @@ llvm::BasicBlock *polly::getUseBlock(const llvm::Use &U) {
return UI->getParent();
}
std::tuple<std::vector<const SCEV *>, std::vector<int>>
polly::getIndexExpressionsFromGEP(GetElementPtrInst *GEP, ScalarEvolution &SE) {
std::vector<const SCEV *> Subscripts;
std::vector<int> Sizes;
Type *Ty = GEP->getPointerOperandType();
bool DroppedFirstDim = false;
for (unsigned i = 1; i < GEP->getNumOperands(); i++) {
const SCEV *Expr = SE.getSCEV(GEP->getOperand(i));
if (i == 1) {
if (auto *PtrTy = dyn_cast<PointerType>(Ty)) {
Ty = PtrTy->getElementType();
} else if (auto *ArrayTy = dyn_cast<ArrayType>(Ty)) {
Ty = ArrayTy->getElementType();
} else {
Subscripts.clear();
Sizes.clear();
break;
}
if (auto *Const = dyn_cast<SCEVConstant>(Expr))
if (Const->getValue()->isZero()) {
DroppedFirstDim = true;
continue;
}
Subscripts.push_back(Expr);
continue;
}
auto *ArrayTy = dyn_cast<ArrayType>(Ty);
if (!ArrayTy) {
Subscripts.clear();
Sizes.clear();
break;
}
Subscripts.push_back(Expr);
if (!(DroppedFirstDim && i == 2))
Sizes.push_back(ArrayTy->getNumElements());
Ty = ArrayTy->getElementType();
}
return std::make_tuple(Subscripts, Sizes);
}
llvm::Loop *polly::getFirstNonBoxedLoopFor(llvm::Loop *L, llvm::LoopInfo &LI,
const BoxedLoopsSetTy &BoxedLoops) {
while (BoxedLoops.count(L))