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::BasicBlock *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    BasicBlock *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.
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.