172448525SMichael Kruse //===- LoopTransformWarning.cpp - ----------------------------------------===//
272448525SMichael Kruse //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
672448525SMichael Kruse //
772448525SMichael Kruse //===----------------------------------------------------------------------===//
872448525SMichael Kruse //
972448525SMichael Kruse // Emit warnings if forced code transformations have not been performed.
1072448525SMichael Kruse //
1172448525SMichael Kruse //===----------------------------------------------------------------------===//
1272448525SMichael Kruse
1372448525SMichael Kruse #include "llvm/Transforms/Scalar/WarnMissedTransforms.h"
14a7aaadc1SFlorian Hahn #include "llvm/Analysis/LoopInfo.h"
1572448525SMichael Kruse #include "llvm/Analysis/OptimizationRemarkEmitter.h"
1605da2fe5SReid Kleckner #include "llvm/InitializePasses.h"
1772448525SMichael Kruse #include "llvm/Transforms/Utils/LoopUtils.h"
1872448525SMichael Kruse
1972448525SMichael Kruse using namespace llvm;
2072448525SMichael Kruse
2172448525SMichael Kruse #define DEBUG_TYPE "transform-warning"
2272448525SMichael Kruse
2372448525SMichael Kruse /// Emit warnings for forced (i.e. user-defined) loop transformations which have
2472448525SMichael Kruse /// still not been performed.
warnAboutLeftoverTransformations(Loop * L,OptimizationRemarkEmitter * ORE)2572448525SMichael Kruse static void warnAboutLeftoverTransformations(Loop *L,
2672448525SMichael Kruse OptimizationRemarkEmitter *ORE) {
2772448525SMichael Kruse if (hasUnrollTransformation(L) == TM_ForcedByUser) {
2872448525SMichael Kruse LLVM_DEBUG(dbgs() << "Leftover unroll transformation\n");
2972448525SMichael Kruse ORE->emit(
3072448525SMichael Kruse DiagnosticInfoOptimizationFailure(DEBUG_TYPE,
3172448525SMichael Kruse "FailedRequestedUnrolling",
3272448525SMichael Kruse L->getStartLoc(), L->getHeader())
3372448525SMichael Kruse << "loop not unrolled: the optimizer was unable to perform the "
3472448525SMichael Kruse "requested transformation; the transformation might be disabled or "
3572448525SMichael Kruse "specified as part of an unsupported transformation ordering");
3672448525SMichael Kruse }
3772448525SMichael Kruse
3872448525SMichael Kruse if (hasUnrollAndJamTransformation(L) == TM_ForcedByUser) {
3972448525SMichael Kruse LLVM_DEBUG(dbgs() << "Leftover unroll-and-jam transformation\n");
4072448525SMichael Kruse ORE->emit(
4172448525SMichael Kruse DiagnosticInfoOptimizationFailure(DEBUG_TYPE,
4272448525SMichael Kruse "FailedRequestedUnrollAndJamming",
4372448525SMichael Kruse L->getStartLoc(), L->getHeader())
4472448525SMichael Kruse << "loop not unroll-and-jammed: the optimizer was unable to perform "
4572448525SMichael Kruse "the requested transformation; the transformation might be disabled "
4672448525SMichael Kruse "or specified as part of an unsupported transformation ordering");
4772448525SMichael Kruse }
4872448525SMichael Kruse
4972448525SMichael Kruse if (hasVectorizeTransformation(L) == TM_ForcedByUser) {
5072448525SMichael Kruse LLVM_DEBUG(dbgs() << "Leftover vectorization transformation\n");
5171bd59f0SDavid Sherwood Optional<ElementCount> VectorizeWidth =
5271bd59f0SDavid Sherwood getOptionalElementCountLoopAttribute(L);
5372448525SMichael Kruse Optional<int> InterleaveCount =
5472448525SMichael Kruse getOptionalIntLoopAttribute(L, "llvm.loop.interleave.count");
5572448525SMichael Kruse
5671bd59f0SDavid Sherwood if (!VectorizeWidth || VectorizeWidth->isVector())
5772448525SMichael Kruse ORE->emit(
5872448525SMichael Kruse DiagnosticInfoOptimizationFailure(DEBUG_TYPE,
5972448525SMichael Kruse "FailedRequestedVectorization",
6072448525SMichael Kruse L->getStartLoc(), L->getHeader())
6172448525SMichael Kruse << "loop not vectorized: the optimizer was unable to perform the "
6272448525SMichael Kruse "requested transformation; the transformation might be disabled "
6372448525SMichael Kruse "or specified as part of an unsupported transformation ordering");
64*129b531cSKazu Hirata else if (InterleaveCount.value_or(0) != 1)
6572448525SMichael Kruse ORE->emit(
6672448525SMichael Kruse DiagnosticInfoOptimizationFailure(DEBUG_TYPE,
6772448525SMichael Kruse "FailedRequestedInterleaving",
6872448525SMichael Kruse L->getStartLoc(), L->getHeader())
6972448525SMichael Kruse << "loop not interleaved: the optimizer was unable to perform the "
7072448525SMichael Kruse "requested transformation; the transformation might be disabled "
7172448525SMichael Kruse "or specified as part of an unsupported transformation ordering");
7272448525SMichael Kruse }
7372448525SMichael Kruse
7472448525SMichael Kruse if (hasDistributeTransformation(L) == TM_ForcedByUser) {
7572448525SMichael Kruse LLVM_DEBUG(dbgs() << "Leftover distribute transformation\n");
7672448525SMichael Kruse ORE->emit(
7772448525SMichael Kruse DiagnosticInfoOptimizationFailure(DEBUG_TYPE,
7872448525SMichael Kruse "FailedRequestedDistribution",
7972448525SMichael Kruse L->getStartLoc(), L->getHeader())
8072448525SMichael Kruse << "loop not distributed: the optimizer was unable to perform the "
8172448525SMichael Kruse "requested transformation; the transformation might be disabled or "
8272448525SMichael Kruse "specified as part of an unsupported transformation ordering");
8372448525SMichael Kruse }
8472448525SMichael Kruse }
8572448525SMichael Kruse
warnAboutLeftoverTransformations(Function * F,LoopInfo * LI,OptimizationRemarkEmitter * ORE)8672448525SMichael Kruse static void warnAboutLeftoverTransformations(Function *F, LoopInfo *LI,
8772448525SMichael Kruse OptimizationRemarkEmitter *ORE) {
8872448525SMichael Kruse for (auto *L : LI->getLoopsInPreorder())
8972448525SMichael Kruse warnAboutLeftoverTransformations(L, ORE);
9072448525SMichael Kruse }
9172448525SMichael Kruse
9272448525SMichael Kruse // New pass manager boilerplate
9372448525SMichael Kruse PreservedAnalyses
run(Function & F,FunctionAnalysisManager & AM)9472448525SMichael Kruse WarnMissedTransformationsPass::run(Function &F, FunctionAnalysisManager &AM) {
95ea9ef345SMichael Kruse // Do not warn about not applied transformations if optimizations are
96ea9ef345SMichael Kruse // disabled.
9785bd3978SEvandro Menezes if (F.hasOptNone())
98ea9ef345SMichael Kruse return PreservedAnalyses::all();
99ea9ef345SMichael Kruse
10072448525SMichael Kruse auto &ORE = AM.getResult<OptimizationRemarkEmitterAnalysis>(F);
10172448525SMichael Kruse auto &LI = AM.getResult<LoopAnalysis>(F);
10272448525SMichael Kruse
10372448525SMichael Kruse warnAboutLeftoverTransformations(&F, &LI, &ORE);
10472448525SMichael Kruse
10572448525SMichael Kruse return PreservedAnalyses::all();
10672448525SMichael Kruse }
10772448525SMichael Kruse
10872448525SMichael Kruse // Legacy pass manager boilerplate
10972448525SMichael Kruse namespace {
11072448525SMichael Kruse class WarnMissedTransformationsLegacy : public FunctionPass {
11172448525SMichael Kruse public:
11272448525SMichael Kruse static char ID;
11372448525SMichael Kruse
WarnMissedTransformationsLegacy()11472448525SMichael Kruse explicit WarnMissedTransformationsLegacy() : FunctionPass(ID) {
11572448525SMichael Kruse initializeWarnMissedTransformationsLegacyPass(
11672448525SMichael Kruse *PassRegistry::getPassRegistry());
11772448525SMichael Kruse }
11872448525SMichael Kruse
runOnFunction(Function & F)11972448525SMichael Kruse bool runOnFunction(Function &F) override {
12072448525SMichael Kruse if (skipFunction(F))
12172448525SMichael Kruse return false;
12272448525SMichael Kruse
12372448525SMichael Kruse auto &ORE = getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE();
12472448525SMichael Kruse auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
12572448525SMichael Kruse
12672448525SMichael Kruse warnAboutLeftoverTransformations(&F, &LI, &ORE);
12772448525SMichael Kruse return false;
12872448525SMichael Kruse }
12972448525SMichael Kruse
getAnalysisUsage(AnalysisUsage & AU) const13072448525SMichael Kruse void getAnalysisUsage(AnalysisUsage &AU) const override {
13172448525SMichael Kruse AU.addRequired<OptimizationRemarkEmitterWrapperPass>();
13272448525SMichael Kruse AU.addRequired<LoopInfoWrapperPass>();
13372448525SMichael Kruse
13472448525SMichael Kruse AU.setPreservesAll();
13572448525SMichael Kruse }
13672448525SMichael Kruse };
13772448525SMichael Kruse } // end anonymous namespace
13872448525SMichael Kruse
13972448525SMichael Kruse char WarnMissedTransformationsLegacy::ID = 0;
14072448525SMichael Kruse
14172448525SMichael Kruse INITIALIZE_PASS_BEGIN(WarnMissedTransformationsLegacy, "transform-warning",
14272448525SMichael Kruse "Warn about non-applied transformations", false, false)
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)14372448525SMichael Kruse INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
14472448525SMichael Kruse INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass)
14572448525SMichael Kruse INITIALIZE_PASS_END(WarnMissedTransformationsLegacy, "transform-warning",
14672448525SMichael Kruse "Warn about non-applied transformations", false, false)
14772448525SMichael Kruse
14872448525SMichael Kruse Pass *llvm::createWarnMissedTransformationsPass() {
14972448525SMichael Kruse return new WarnMissedTransformationsLegacy();
15072448525SMichael Kruse }
151