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