Files
clang-p2996/polly/lib/Analysis/PolyhedralInfo.cpp
Reid Kleckner 05da2fe521 Sink all InitializePasses.h includes
This file lists every pass in LLVM, and is included by Pass.h, which is
very popular. Every time we add, remove, or rename a pass in LLVM, it
caused lots of recompilation.

I found this fact by looking at this table, which is sorted by the
number of times a file was changed over the last 100,000 git commits
multiplied by the number of object files that depend on it in the
current checkout:
  recompiles    touches affected_files  header
  342380        95      3604    llvm/include/llvm/ADT/STLExtras.h
  314730        234     1345    llvm/include/llvm/InitializePasses.h
  307036        118     2602    llvm/include/llvm/ADT/APInt.h
  213049        59      3611    llvm/include/llvm/Support/MathExtras.h
  170422        47      3626    llvm/include/llvm/Support/Compiler.h
  162225        45      3605    llvm/include/llvm/ADT/Optional.h
  158319        63      2513    llvm/include/llvm/ADT/Triple.h
  140322        39      3598    llvm/include/llvm/ADT/StringRef.h
  137647        59      2333    llvm/include/llvm/Support/Error.h
  131619        73      1803    llvm/include/llvm/Support/FileSystem.h

Before this change, touching InitializePasses.h would cause 1345 files
to recompile. After this change, touching it only causes 550 compiles in
an incremental rebuild.

Reviewers: bkramer, asbirlea, bollu, jdoerfert

Differential Revision: https://reviews.llvm.org/D70211
2019-11-13 16:34:37 -08:00

166 lines
6.1 KiB
C++

//===--------- PolyhedralInfo.cpp - Create Scops from LLVM IR-------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// An interface to the Polyhedral analysis engine(Polly) of LLVM.
//
// This pass provides an interface to the polyhedral analysis performed by
// Polly.
//
// This interface provides basic interface like isParallel, isVectorizable
// that can be used in LLVM transformation passes.
//
// Work in progress, this file is subject to change.
//
//===----------------------------------------------------------------------===//
#include "polly/PolyhedralInfo.h"
#include "polly/DependenceInfo.h"
#include "polly/LinkAllPasses.h"
#include "polly/Options.h"
#include "polly/ScopInfo.h"
#include "polly/Support/GICHelper.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/Debug.h"
#include "isl/union_map.h"
using namespace llvm;
using namespace polly;
#define DEBUG_TYPE "polyhedral-info"
static cl::opt<bool> CheckParallel("polly-check-parallel",
cl::desc("Check for parallel loops"),
cl::Hidden, cl::init(false), cl::ZeroOrMore,
cl::cat(PollyCategory));
static cl::opt<bool> CheckVectorizable("polly-check-vectorizable",
cl::desc("Check for vectorizable loops"),
cl::Hidden, cl::init(false),
cl::ZeroOrMore, cl::cat(PollyCategory));
void PolyhedralInfo::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequiredTransitive<DependenceInfoWrapperPass>();
AU.addRequired<LoopInfoWrapperPass>();
AU.addRequiredTransitive<ScopInfoWrapperPass>();
AU.setPreservesAll();
}
bool PolyhedralInfo::runOnFunction(Function &F) {
DI = &getAnalysis<DependenceInfoWrapperPass>();
SI = getAnalysis<ScopInfoWrapperPass>().getSI();
return false;
}
void PolyhedralInfo::print(raw_ostream &OS, const Module *) const {
auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
for (auto *TopLevelLoop : LI) {
for (auto *L : depth_first(TopLevelLoop)) {
OS.indent(2) << L->getHeader()->getName() << ":\t";
if (CheckParallel && isParallel(L))
OS << "Loop is parallel.\n";
else if (CheckParallel)
OS << "Loop is not parallel.\n";
}
}
}
bool PolyhedralInfo::checkParallel(Loop *L, isl_pw_aff **MinDepDistPtr) const {
bool IsParallel;
const Scop *S = getScopContainingLoop(L);
if (!S)
return false;
const Dependences &D =
DI->getDependences(const_cast<Scop *>(S), Dependences::AL_Access);
if (!D.hasValidDependences())
return false;
LLVM_DEBUG(dbgs() << "Loop :\t" << L->getHeader()->getName() << ":\n");
isl_union_map *Deps =
D.getDependences(Dependences::TYPE_RAW | Dependences::TYPE_WAW |
Dependences::TYPE_WAR | Dependences::TYPE_RED)
.release();
LLVM_DEBUG(dbgs() << "Dependences :\t" << stringFromIslObj(Deps) << "\n");
isl_union_map *Schedule = getScheduleForLoop(S, L);
LLVM_DEBUG(dbgs() << "Schedule: \t" << stringFromIslObj(Schedule) << "\n");
IsParallel = D.isParallel(Schedule, Deps, MinDepDistPtr);
isl_union_map_free(Schedule);
return IsParallel;
}
bool PolyhedralInfo::isParallel(Loop *L) const { return checkParallel(L); }
const Scop *PolyhedralInfo::getScopContainingLoop(Loop *L) const {
assert((SI) && "ScopInfoWrapperPass is required by PolyhedralInfo pass!\n");
for (auto &It : *SI) {
Region *R = It.first;
if (R->contains(L))
return It.second.get();
}
return nullptr;
}
// Given a Loop and the containing SCoP, we compute the partial schedule
// by taking union of individual schedules of each ScopStmt within the loop
// and projecting out the inner dimensions from the range of the schedule.
// for (i = 0; i < n; i++)
// for (j = 0; j < n; j++)
// A[j] = 1; //Stmt
//
// The original schedule will be
// Stmt[i0, i1] -> [i0, i1]
// The schedule for the outer loop will be
// Stmt[i0, i1] -> [i0]
// The schedule for the inner loop will be
// Stmt[i0, i1] -> [i0, i1]
__isl_give isl_union_map *PolyhedralInfo::getScheduleForLoop(const Scop *S,
Loop *L) const {
isl_union_map *Schedule = isl_union_map_empty(S->getParamSpace().release());
int CurrDim = S->getRelativeLoopDepth(L);
LLVM_DEBUG(dbgs() << "Relative loop depth:\t" << CurrDim << "\n");
assert(CurrDim >= 0 && "Loop in region should have at least depth one");
for (auto &SS : *S) {
if (L->contains(SS.getSurroundingLoop())) {
unsigned int MaxDim = SS.getNumIterators();
LLVM_DEBUG(dbgs() << "Maximum depth of Stmt:\t" << MaxDim << "\n");
isl_map *ScheduleMap = SS.getSchedule().release();
assert(
ScheduleMap &&
"Schedules that contain extension nodes require special handling.");
ScheduleMap = isl_map_project_out(ScheduleMap, isl_dim_out, CurrDim + 1,
MaxDim - CurrDim - 1);
ScheduleMap = isl_map_set_tuple_id(ScheduleMap, isl_dim_in,
SS.getDomainId().release());
Schedule =
isl_union_map_union(Schedule, isl_union_map_from_map(ScheduleMap));
}
}
Schedule = isl_union_map_coalesce(Schedule);
return Schedule;
}
char PolyhedralInfo::ID = 0;
Pass *polly::createPolyhedralInfoPass() { return new PolyhedralInfo(); }
INITIALIZE_PASS_BEGIN(PolyhedralInfo, "polyhedral-info",
"Polly - Interface to polyhedral analysis engine", false,
false);
INITIALIZE_PASS_DEPENDENCY(DependenceInfoWrapperPass);
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass);
INITIALIZE_PASS_DEPENDENCY(ScopInfoWrapperPass);
INITIALIZE_PASS_END(PolyhedralInfo, "polyhedral-info",
"Polly - Interface to polyhedral analysis engine", false,
false)