cb424d7448
verify-patch-sanity.py validates every active recipe .patch has internally- consistent hunk line counts — catching the 'malformed patch at line N' failure at commit/CI/preflight time instead of hours into a cook. This cycle hit that class three times (qtwaylandscanner, sddm, xwayland), each only discovered when cookbook tried to apply the patch. Running it across the repo found 29 latent malformed patches (validated against GNU patch: e.g. relibc/P3-sysv-ipc reproduces 'malformed patch at line 22'). They were harmless only because they sit in vendored recipes (baked, not re- applied) — but would fail on any version-bump re-derivation. --fix recounts the hunk headers (body untouched) and repaired all 29. Wired into build-preflight.sh (Phase 1.0D) and redbear-ci.yml, with a unit test (test-patch-sanity.sh). Skips archived/legacy trees and unvalidatable formats (empty placeholders, bare-@@ git hunks).
216 lines
7.5 KiB
C++
216 lines
7.5 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;
|
|
|
|
#include "polly/Support/PollyDebug.h"
|
|
#define DEBUG_TYPE "polyhedral-info"
|
|
|
|
static cl::opt<bool> CheckParallel("polly-check-parallel",
|
|
cl::desc("Check for parallel loops"),
|
|
cl::Hidden, cl::cat(PollyCategory));
|
|
|
|
static cl::opt<bool> CheckVectorizable("polly-check-vectorizable",
|
|
cl::desc("Check for vectorizable loops"),
|
|
cl::Hidden, 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;
|
|
POLLY_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();
|
|
|
|
POLLY_DEBUG(dbgs() << "Dependences :\t" << stringFromIslObj(Deps, "null")
|
|
<< "\n");
|
|
|
|
isl_union_map *Schedule = getScheduleForLoop(S, L);
|
|
POLLY_DEBUG(dbgs() << "Schedule: \t" << stringFromIslObj(Schedule, "null")
|
|
<< "\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);
|
|
POLLY_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();
|
|
POLLY_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)
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
namespace {
|
|
/// Print result from PolyhedralInfo.
|
|
class PolyhedralInfoPrinterLegacyPass final : public FunctionPass {
|
|
public:
|
|
static char ID;
|
|
|
|
PolyhedralInfoPrinterLegacyPass() : PolyhedralInfoPrinterLegacyPass(outs()) {}
|
|
explicit PolyhedralInfoPrinterLegacyPass(llvm::raw_ostream &OS)
|
|
: FunctionPass(ID), OS(OS) {}
|
|
|
|
bool runOnFunction(Function &F) override {
|
|
PolyhedralInfo &P = getAnalysis<PolyhedralInfo>();
|
|
|
|
OS << "Printing analysis '" << P.getPassName() << "' for function '"
|
|
<< F.getName() << "':\n";
|
|
P.print(OS);
|
|
|
|
return false;
|
|
}
|
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
|
FunctionPass::getAnalysisUsage(AU);
|
|
AU.addRequired<PolyhedralInfo>();
|
|
AU.setPreservesAll();
|
|
}
|
|
|
|
private:
|
|
llvm::raw_ostream &OS;
|
|
};
|
|
|
|
char PolyhedralInfoPrinterLegacyPass::ID = 0;
|
|
} // namespace
|
|
|
|
Pass *polly::createPolyhedralInfoPrinterLegacyPass(raw_ostream &OS) {
|
|
return new PolyhedralInfoPrinterLegacyPass(OS);
|
|
}
|
|
|
|
INITIALIZE_PASS_BEGIN(
|
|
PolyhedralInfoPrinterLegacyPass, "print-polyhedral-info",
|
|
"Polly - Print interface to polyhedral analysis engine analysis", false,
|
|
false);
|
|
INITIALIZE_PASS_DEPENDENCY(PolyhedralInfo);
|
|
INITIALIZE_PASS_END(
|
|
PolyhedralInfoPrinterLegacyPass, "print-polyhedral-info",
|
|
"Polly - Print interface to polyhedral analysis engine analysis", false,
|
|
false)
|