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 19 using 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. 25 static 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<ElementCount> VectorizeWidth = 52 getOptionalElementCountLoopAttribute(L); 53 Optional<int> InterleaveCount = 54 getOptionalIntLoopAttribute(L, "llvm.loop.interleave.count"); 55 56 if (!VectorizeWidth || VectorizeWidth->isVector()) 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.value_or(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 86 static 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 93 PreservedAnalyses 94 WarnMissedTransformationsPass::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 109 namespace { 110 class WarnMissedTransformationsLegacy : public FunctionPass { 111 public: 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 139 char WarnMissedTransformationsLegacy::ID = 0; 140 141 INITIALIZE_PASS_BEGIN(WarnMissedTransformationsLegacy, "transform-warning", 142 "Warn about non-applied transformations", false, false) 143 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) 144 INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass) 145 INITIALIZE_PASS_END(WarnMissedTransformationsLegacy, "transform-warning", 146 "Warn about non-applied transformations", false, false) 147 148 Pass *llvm::createWarnMissedTransformationsPass() { 149 return new WarnMissedTransformationsLegacy(); 150 } 151