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