1//===- LoopTransformWarning.cpp -  ----------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Emit warnings if forced code transformations have not been performed.
10//
11//===----------------------------------------------------------------------===//
12
13#include "llvm/Transforms/Scalar/WarnMissedTransforms.h"
14#include "llvm/Analysis/LoopInfo.h"
15#include "llvm/Analysis/OptimizationRemarkEmitter.h"
16#include "llvm/InitializePasses.h"
17#include "llvm/Transforms/Utils/LoopUtils.h"
18
19using namespace llvm;
20
21#define DEBUG_TYPE "transform-warning"
22
23/// Emit warnings for forced (i.e. user-defined) loop transformations which have
24/// still not been performed.
25static void warnAboutLeftoverTransformations(Loop *L,
26                                             OptimizationRemarkEmitter *ORE) {
27  if (hasUnrollTransformation(L) == TM_ForcedByUser) {
28    LLVM_DEBUG(dbgs() << "Leftover unroll transformation\n");
29    ORE->emit(
30        DiagnosticInfoOptimizationFailure(DEBUG_TYPE,
31                                          "FailedRequestedUnrolling",
32                                          L->getStartLoc(), L->getHeader())
33        << "loop not unrolled: the optimizer was unable to perform the "
34           "requested transformation; the transformation might be disabled or "
35           "specified as part of an unsupported transformation ordering");
36  }
37
38  if (hasUnrollAndJamTransformation(L) == TM_ForcedByUser) {
39    LLVM_DEBUG(dbgs() << "Leftover unroll-and-jam transformation\n");
40    ORE->emit(
41        DiagnosticInfoOptimizationFailure(DEBUG_TYPE,
42                                          "FailedRequestedUnrollAndJamming",
43                                          L->getStartLoc(), L->getHeader())
44        << "loop not unroll-and-jammed: the optimizer was unable to perform "
45           "the requested transformation; the transformation might be disabled "
46           "or specified as part of an unsupported transformation ordering");
47  }
48
49  if (hasVectorizeTransformation(L) == TM_ForcedByUser) {
50    LLVM_DEBUG(dbgs() << "Leftover vectorization transformation\n");
51    Optional<int> VectorizeWidth =
52        getOptionalIntLoopAttribute(L, "llvm.loop.vectorize.width");
53    Optional<int> InterleaveCount =
54        getOptionalIntLoopAttribute(L, "llvm.loop.interleave.count");
55
56    if (VectorizeWidth.getValueOr(0) != 1)
57      ORE->emit(
58          DiagnosticInfoOptimizationFailure(DEBUG_TYPE,
59                                            "FailedRequestedVectorization",
60                                            L->getStartLoc(), L->getHeader())
61          << "loop not vectorized: the optimizer was unable to perform the "
62             "requested transformation; the transformation might be disabled "
63             "or specified as part of an unsupported transformation ordering");
64    else if (InterleaveCount.getValueOr(0) != 1)
65      ORE->emit(
66          DiagnosticInfoOptimizationFailure(DEBUG_TYPE,
67                                            "FailedRequestedInterleaving",
68                                            L->getStartLoc(), L->getHeader())
69          << "loop not interleaved: the optimizer was unable to perform the "
70             "requested transformation; the transformation might be disabled "
71             "or specified as part of an unsupported transformation ordering");
72  }
73
74  if (hasDistributeTransformation(L) == TM_ForcedByUser) {
75    LLVM_DEBUG(dbgs() << "Leftover distribute transformation\n");
76    ORE->emit(
77        DiagnosticInfoOptimizationFailure(DEBUG_TYPE,
78                                          "FailedRequestedDistribution",
79                                          L->getStartLoc(), L->getHeader())
80        << "loop not distributed: the optimizer was unable to perform the "
81           "requested transformation; the transformation might be disabled or "
82           "specified as part of an unsupported transformation ordering");
83  }
84}
85
86static void warnAboutLeftoverTransformations(Function *F, LoopInfo *LI,
87                                             OptimizationRemarkEmitter *ORE) {
88  for (auto *L : LI->getLoopsInPreorder())
89    warnAboutLeftoverTransformations(L, ORE);
90}
91
92// New pass manager boilerplate
93PreservedAnalyses
94WarnMissedTransformationsPass::run(Function &F, FunctionAnalysisManager &AM) {
95  // Do not warn about not applied transformations if optimizations are
96  // disabled.
97  if (F.hasOptNone())
98    return PreservedAnalyses::all();
99
100  auto &ORE = AM.getResult<OptimizationRemarkEmitterAnalysis>(F);
101  auto &LI = AM.getResult<LoopAnalysis>(F);
102
103  warnAboutLeftoverTransformations(&F, &LI, &ORE);
104
105  return PreservedAnalyses::all();
106}
107
108// Legacy pass manager boilerplate
109namespace {
110class WarnMissedTransformationsLegacy : public FunctionPass {
111public:
112  static char ID;
113
114  explicit WarnMissedTransformationsLegacy() : FunctionPass(ID) {
115    initializeWarnMissedTransformationsLegacyPass(
116        *PassRegistry::getPassRegistry());
117  }
118
119  bool runOnFunction(Function &F) override {
120    if (skipFunction(F))
121      return false;
122
123    auto &ORE = getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE();
124    auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
125
126    warnAboutLeftoverTransformations(&F, &LI, &ORE);
127    return false;
128  }
129
130  void getAnalysisUsage(AnalysisUsage &AU) const override {
131    AU.addRequired<OptimizationRemarkEmitterWrapperPass>();
132    AU.addRequired<LoopInfoWrapperPass>();
133
134    AU.setPreservesAll();
135  }
136};
137} // end anonymous namespace
138
139char WarnMissedTransformationsLegacy::ID = 0;
140
141INITIALIZE_PASS_BEGIN(WarnMissedTransformationsLegacy, "transform-warning",
142                      "Warn about non-applied transformations", false, false)
143INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
144INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass)
145INITIALIZE_PASS_END(WarnMissedTransformationsLegacy, "transform-warning",
146                    "Warn about non-applied transformations", false, false)
147
148Pass *llvm::createWarnMissedTransformationsPass() {
149  return new WarnMissedTransformationsLegacy();
150}
151