18#include "llvm/ADT/StringRef.h"
19#include "llvm/Analysis/LoopInfo.h"
20#include "llvm/Analysis/OptimizationRemarkEmitter.h"
21#include "llvm/IR/Metadata.h"
22#include "llvm/Transforms/Utils/LoopUtils.h"
26#define DEBUG_TYPE "polly-opt-manual"
33static cl::opt<bool> IgnoreDepcheck(
34 "polly-pragma-ignore-depcheck",
35 cl::desc(
"Skip the dependency check for pragma-based transformations"),
40static TransformationMode hasUnrollTransformation(MDNode *LoopID) {
42 return TM_SuppressedByUser;
44 std::optional<int> Count =
47 return *Count == 1 ? TM_SuppressedByUser : TM_ForcedByUser;
50 return TM_ForcedByUser;
53 return TM_ForcedByUser;
58 return TM_Unspecified;
62static DebugLoc findFirstDebugLoc(MDNode *MD) {
64 for (
const MDOperand &
X : drop_begin(MD->operands(), 1)) {
65 Metadata *
A =
X.get();
66 if (!isa<DILocation>(
A))
68 return cast<DILocation>(
A);
75static DebugLoc findTransformationDebugLoc(MDNode *LoopMD, StringRef Name) {
78 MDNode *MD = findOptionMDForLoopID(LoopMD, Name);
79 if (DebugLoc K = findFirstDebugLoc(MD))
83 return findFirstDebugLoc(LoopMD);
89 TransformationMode UnrollMode = ::hasUnrollTransformation(LoopMD);
90 if (UnrollMode & TM_Disable)
103 assert((!Full || !(Factor > 0)) &&
104 "Cannot unroll fully and partially at the same time");
126static auto getLoopMDProps(MDNode *LoopMD) {
129 drop_begin(LoopMD->operands(), 1),
130 [](
const MDOperand &MDOp) { return isa<MDNode>(MDOp.get()); }),
131 [](
const MDOperand &MDOp) { return cast<MDNode>(MDOp.get()); });
136class SearchTransformVisitor final
140 BaseTy &
getBase() {
return *
this; }
141 const BaseTy &
getBase()
const {
return *
this; }
145 OptimizationRemarkEmitter *ORE;
155 checkDependencyViolation(llvm::MDNode *LoopMD, llvm::Value *CodeRegion,
157 StringRef DebugLocAttr, StringRef TransPrefix,
158 StringRef RemarkName, StringRef TransformationName) {
162 LLVMContext &
Ctx = LoopMD->getContext();
163 POLLY_DEBUG(dbgs() <<
"Dependency violation detected\n");
165 DebugLoc TransformLoc = findTransformationDebugLoc(LoopMD, DebugLocAttr);
167 if (IgnoreDepcheck) {
168 POLLY_DEBUG(dbgs() <<
"Still accepting transformation due to "
169 "-polly-pragma-ignore-depcheck\n");
172 OptimizationRemark(
DEBUG_TYPE, RemarkName, TransformLoc, CodeRegion)
173 << (Twine(
"Could not verify dependencies for ") +
175 "; still applying because of -polly-pragma-ignore-depcheck")
181 POLLY_DEBUG(dbgs() <<
"Rolling back transformation\n");
184 ORE->emit(DiagnosticInfoOptimizationFailure(
DEBUG_TYPE, RemarkName,
185 TransformLoc, CodeRegion)
186 << (Twine(
"not applying ") + TransformationName +
187 ": cannot ensure semantic equivalence due to possible "
188 "dependency violations")
195 makePostTransformationMetadata(
Ctx, LoopMD, {TransPrefix}, {});
197 Attr->Metadata = NewLoopMD;
205 OptimizationRemarkEmitter *ORE)
206 :
S(
S), D(D), ORE(ORE) {}
210 OptimizationRemarkEmitter *ORE,
212 SearchTransformVisitor Transformer(
S, D, ORE);
213 Transformer.visit(Sched);
214 return Transformer.Result;
219 getBase().visitBand(Band);
238 Value *CodeRegion =
nullptr;
240 CodeRegion = Loop->getHeader();
249 for (MDNode *MD : getLoopMDProps(LoopMD)) {
250 auto *NameMD = dyn_cast<MDString>(MD->getOperand(0).get());
253 StringRef AttrName = NameMD->getString();
257 if (AttrName ==
"llvm.loop.unroll.enable" ||
258 AttrName ==
"llvm.loop.unroll.count" ||
259 AttrName ==
"llvm.loop.unroll.full") {
260 Result = applyLoopUnroll(LoopMD, Band);
263 }
else if (AttrName ==
"llvm.loop.distribute.enable") {
264 Result = applyLoopFission(LoopMD, Band);
266 Result = checkDependencyViolation(
267 LoopMD, CodeRegion, Band,
"llvm.loop.distribute.loc",
268 "llvm.loop.distribute.",
"FailedRequestedFission",
269 "loop fission/distribution");
281 getBase().visitNode(
Other);
290 OptimizationRemarkEmitter *ORE) {
294 SearchTransformVisitor::applyOneTransformation(
S, &D, ORE, Sched);
llvm::cl::OptionCategory PollyCategory
static RegisterPass< ScopViewerWrapperPass > X("view-scops", "Polly - View Scops of function")
isl::schedule get_schedule() const
__isl_keep isl_schedule_node * get() const
The accumulated dependence information for a SCoP.
bool isValidSchedule(Scop &S, const StatementToIslMapTy &NewSchedules) const
Check if a new schedule is valid.
This file contains the declaration of the PolyhedralInfo class, which will provide an interface to ex...
@ Value
MemoryKind::Value: Models an llvm::Value.
isl::schedule applyManualTransformations(Scop *S, isl::schedule Sched, const Dependences &D, llvm::OptimizationRemarkEmitter *ORE)
Apply loop-transformation metadata.
bool hasDisableAllTransformsHint(llvm::Loop *L)
Does the loop's LoopID contain a 'llvm.loop.disable_heuristics' property?
std::optional< int > getOptionalIntLoopAttribute(llvm::MDNode *LoopID, llvm::StringRef Name)
Find an integers property value in a LoopID.
BandAttr * getBandAttr(isl::schedule_node MarkOrBand)
Extract the BandAttr from a band's wrapping marker.
isl::schedule applyMaxFission(isl::schedule_node BandToFission)
Loop-distribute the band BandToFission as much as possible.
isl::schedule applyPartialUnroll(isl::schedule_node BandToUnroll, int Factor)
Replace the AST band BandToUnroll by a partially unrolled equivalent.
bool getBooleanLoopAttribute(llvm::MDNode *LoopID, llvm::StringRef Name)
Find a boolean property value in a LoopID.
isl::schedule applyFullUnroll(isl::schedule_node BandToUnroll)
Replace the AST band BandToUnroll by a sequence of all its iterations.
__isl_export isl_size isl_schedule_node_band_n_member(__isl_keep isl_schedule_node *node)
Represent the attributes of a loop.
llvm::MDNode * Metadata
LoopID which stores the properties of the loop, such as transformations to apply and the metadata of ...
llvm::Loop * OriginalLoop
The LoopInfo reference for this loop.
Recursively visit all nodes of a schedule tree.