1c76acb9dSJay Foad //===- UniformityAnalysis.cpp ---------------------------------------------===// 2475ce4c2SSameer Sahasrabuddhe // 3475ce4c2SSameer Sahasrabuddhe // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4475ce4c2SSameer Sahasrabuddhe // See https://llvm.org/LICENSE.txt for license information. 5475ce4c2SSameer Sahasrabuddhe // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6475ce4c2SSameer Sahasrabuddhe // 7475ce4c2SSameer Sahasrabuddhe //===----------------------------------------------------------------------===// 8475ce4c2SSameer Sahasrabuddhe 9475ce4c2SSameer Sahasrabuddhe #include "llvm/Analysis/UniformityAnalysis.h" 10475ce4c2SSameer Sahasrabuddhe #include "llvm/ADT/GenericUniformityImpl.h" 11475ce4c2SSameer Sahasrabuddhe #include "llvm/Analysis/CycleAnalysis.h" 12475ce4c2SSameer Sahasrabuddhe #include "llvm/Analysis/TargetTransformInfo.h" 13475ce4c2SSameer Sahasrabuddhe #include "llvm/IR/Dominators.h" 14475ce4c2SSameer Sahasrabuddhe #include "llvm/IR/InstIterator.h" 15475ce4c2SSameer Sahasrabuddhe #include "llvm/IR/Instructions.h" 16475ce4c2SSameer Sahasrabuddhe #include "llvm/InitializePasses.h" 17475ce4c2SSameer Sahasrabuddhe 18475ce4c2SSameer Sahasrabuddhe using namespace llvm; 19475ce4c2SSameer Sahasrabuddhe 20475ce4c2SSameer Sahasrabuddhe template <> 21475ce4c2SSameer Sahasrabuddhe bool llvm::GenericUniformityAnalysisImpl<SSAContext>::hasDivergentDefs( 22475ce4c2SSameer Sahasrabuddhe const Instruction &I) const { 23475ce4c2SSameer Sahasrabuddhe return isDivergent((const Value *)&I); 24475ce4c2SSameer Sahasrabuddhe } 25475ce4c2SSameer Sahasrabuddhe 26475ce4c2SSameer Sahasrabuddhe template <> 27475ce4c2SSameer Sahasrabuddhe bool llvm::GenericUniformityAnalysisImpl<SSAContext>::markDefsDivergent( 28fbe1c061SSameer Sahasrabuddhe const Instruction &Instr) { 290a170eb7SSameer Sahasrabuddhe return markDivergent(cast<Value>(&Instr)); 30475ce4c2SSameer Sahasrabuddhe } 31475ce4c2SSameer Sahasrabuddhe 32475ce4c2SSameer Sahasrabuddhe template <> void llvm::GenericUniformityAnalysisImpl<SSAContext>::initialize() { 33475ce4c2SSameer Sahasrabuddhe for (auto &I : instructions(F)) { 34dbebebf6Spvanhout if (TTI->isSourceOfDivergence(&I)) 35475ce4c2SSameer Sahasrabuddhe markDivergent(I); 36dbebebf6Spvanhout else if (TTI->isAlwaysUniform(&I)) 37475ce4c2SSameer Sahasrabuddhe addUniformOverride(I); 38475ce4c2SSameer Sahasrabuddhe } 39475ce4c2SSameer Sahasrabuddhe for (auto &Arg : F.args()) { 40475ce4c2SSameer Sahasrabuddhe if (TTI->isSourceOfDivergence(&Arg)) { 41475ce4c2SSameer Sahasrabuddhe markDivergent(&Arg); 42475ce4c2SSameer Sahasrabuddhe } 43475ce4c2SSameer Sahasrabuddhe } 44475ce4c2SSameer Sahasrabuddhe } 45475ce4c2SSameer Sahasrabuddhe 46475ce4c2SSameer Sahasrabuddhe template <> 47475ce4c2SSameer Sahasrabuddhe void llvm::GenericUniformityAnalysisImpl<SSAContext>::pushUsers( 48475ce4c2SSameer Sahasrabuddhe const Value *V) { 49475ce4c2SSameer Sahasrabuddhe for (const auto *User : V->users()) { 50fd98416dSSameer Sahasrabuddhe if (const auto *UserInstr = dyn_cast<const Instruction>(User)) { 510a170eb7SSameer Sahasrabuddhe markDivergent(*UserInstr); 52475ce4c2SSameer Sahasrabuddhe } 53475ce4c2SSameer Sahasrabuddhe } 54fd98416dSSameer Sahasrabuddhe } 55475ce4c2SSameer Sahasrabuddhe 56475ce4c2SSameer Sahasrabuddhe template <> 57475ce4c2SSameer Sahasrabuddhe void llvm::GenericUniformityAnalysisImpl<SSAContext>::pushUsers( 58475ce4c2SSameer Sahasrabuddhe const Instruction &Instr) { 59475ce4c2SSameer Sahasrabuddhe assert(!isAlwaysUniform(Instr)); 60475ce4c2SSameer Sahasrabuddhe if (Instr.isTerminator()) 61475ce4c2SSameer Sahasrabuddhe return; 62475ce4c2SSameer Sahasrabuddhe pushUsers(cast<Value>(&Instr)); 63475ce4c2SSameer Sahasrabuddhe } 64475ce4c2SSameer Sahasrabuddhe 65475ce4c2SSameer Sahasrabuddhe template <> 66475ce4c2SSameer Sahasrabuddhe bool llvm::GenericUniformityAnalysisImpl<SSAContext>::usesValueFromCycle( 67475ce4c2SSameer Sahasrabuddhe const Instruction &I, const Cycle &DefCycle) const { 685230f6c1SYashwant Singh assert(!isAlwaysUniform(I)); 69475ce4c2SSameer Sahasrabuddhe for (const Use &U : I.operands()) { 70475ce4c2SSameer Sahasrabuddhe if (auto *I = dyn_cast<Instruction>(&U)) { 71475ce4c2SSameer Sahasrabuddhe if (DefCycle.contains(I->getParent())) 72475ce4c2SSameer Sahasrabuddhe return true; 73475ce4c2SSameer Sahasrabuddhe } 74475ce4c2SSameer Sahasrabuddhe } 75475ce4c2SSameer Sahasrabuddhe return false; 76475ce4c2SSameer Sahasrabuddhe } 77475ce4c2SSameer Sahasrabuddhe 78f90849dfSpvanhout template <> 79b0f0dd25SSameer Sahasrabuddhe void llvm::GenericUniformityAnalysisImpl< 80b0f0dd25SSameer Sahasrabuddhe SSAContext>::propagateTemporalDivergence(const Instruction &I, 81b0f0dd25SSameer Sahasrabuddhe const Cycle &DefCycle) { 82b0f0dd25SSameer Sahasrabuddhe if (isDivergent(I)) 83b0f0dd25SSameer Sahasrabuddhe return; 84b0f0dd25SSameer Sahasrabuddhe for (auto *User : I.users()) { 85b0f0dd25SSameer Sahasrabuddhe auto *UserInstr = cast<Instruction>(User); 86b0f0dd25SSameer Sahasrabuddhe if (DefCycle.contains(UserInstr->getParent())) 87b0f0dd25SSameer Sahasrabuddhe continue; 880a170eb7SSameer Sahasrabuddhe markDivergent(*UserInstr); 89b0f0dd25SSameer Sahasrabuddhe } 90b0f0dd25SSameer Sahasrabuddhe } 91b0f0dd25SSameer Sahasrabuddhe 92b0f0dd25SSameer Sahasrabuddhe template <> 93f90849dfSpvanhout bool llvm::GenericUniformityAnalysisImpl<SSAContext>::isDivergentUse( 94f90849dfSpvanhout const Use &U) const { 95f90849dfSpvanhout const auto *V = U.get(); 96f90849dfSpvanhout if (isDivergent(V)) 97f90849dfSpvanhout return true; 98f90849dfSpvanhout if (const auto *DefInstr = dyn_cast<Instruction>(V)) { 99f90849dfSpvanhout const auto *UseInstr = cast<Instruction>(U.getUser()); 100f90849dfSpvanhout return isTemporalDivergent(*UseInstr->getParent(), *DefInstr); 101f90849dfSpvanhout } 102f90849dfSpvanhout return false; 103f90849dfSpvanhout } 104f90849dfSpvanhout 105475ce4c2SSameer Sahasrabuddhe // This ensures explicit instantiation of 106475ce4c2SSameer Sahasrabuddhe // GenericUniformityAnalysisImpl::ImplDeleter::operator() 107475ce4c2SSameer Sahasrabuddhe template class llvm::GenericUniformityInfo<SSAContext>; 1085d98dc71SKrzysztof Drewniak template struct llvm::GenericUniformityAnalysisImplDeleter< 1095d98dc71SKrzysztof Drewniak llvm::GenericUniformityAnalysisImpl<SSAContext>>; 110475ce4c2SSameer Sahasrabuddhe 111475ce4c2SSameer Sahasrabuddhe //===----------------------------------------------------------------------===// 112475ce4c2SSameer Sahasrabuddhe // UniformityInfoAnalysis and related pass implementations 113475ce4c2SSameer Sahasrabuddhe //===----------------------------------------------------------------------===// 114475ce4c2SSameer Sahasrabuddhe 115475ce4c2SSameer Sahasrabuddhe llvm::UniformityInfo UniformityInfoAnalysis::run(Function &F, 116475ce4c2SSameer Sahasrabuddhe FunctionAnalysisManager &FAM) { 117475ce4c2SSameer Sahasrabuddhe auto &DT = FAM.getResult<DominatorTreeAnalysis>(F); 118475ce4c2SSameer Sahasrabuddhe auto &TTI = FAM.getResult<TargetIRAnalysis>(F); 119475ce4c2SSameer Sahasrabuddhe auto &CI = FAM.getResult<CycleAnalysis>(F); 120*b14e30f1SSameer Sahasrabuddhe UniformityInfo UI{DT, CI, &TTI}; 121d61cba6dSMatt Arsenault // Skip computation if we can assume everything is uniform. 12253fb907dSMatt Arsenault if (TTI.hasBranchDivergence(&F)) 123d61cba6dSMatt Arsenault UI.compute(); 124d61cba6dSMatt Arsenault 125d61cba6dSMatt Arsenault return UI; 126475ce4c2SSameer Sahasrabuddhe } 127475ce4c2SSameer Sahasrabuddhe 128475ce4c2SSameer Sahasrabuddhe AnalysisKey UniformityInfoAnalysis::Key; 129475ce4c2SSameer Sahasrabuddhe 130475ce4c2SSameer Sahasrabuddhe UniformityInfoPrinterPass::UniformityInfoPrinterPass(raw_ostream &OS) 131475ce4c2SSameer Sahasrabuddhe : OS(OS) {} 132475ce4c2SSameer Sahasrabuddhe 133475ce4c2SSameer Sahasrabuddhe PreservedAnalyses UniformityInfoPrinterPass::run(Function &F, 134475ce4c2SSameer Sahasrabuddhe FunctionAnalysisManager &AM) { 135475ce4c2SSameer Sahasrabuddhe OS << "UniformityInfo for function '" << F.getName() << "':\n"; 136475ce4c2SSameer Sahasrabuddhe AM.getResult<UniformityInfoAnalysis>(F).print(OS); 137475ce4c2SSameer Sahasrabuddhe 138475ce4c2SSameer Sahasrabuddhe return PreservedAnalyses::all(); 139475ce4c2SSameer Sahasrabuddhe } 140475ce4c2SSameer Sahasrabuddhe 141475ce4c2SSameer Sahasrabuddhe //===----------------------------------------------------------------------===// 142475ce4c2SSameer Sahasrabuddhe // UniformityInfoWrapperPass Implementation 143475ce4c2SSameer Sahasrabuddhe //===----------------------------------------------------------------------===// 144475ce4c2SSameer Sahasrabuddhe 145475ce4c2SSameer Sahasrabuddhe char UniformityInfoWrapperPass::ID = 0; 146475ce4c2SSameer Sahasrabuddhe 147475ce4c2SSameer Sahasrabuddhe UniformityInfoWrapperPass::UniformityInfoWrapperPass() : FunctionPass(ID) { 148475ce4c2SSameer Sahasrabuddhe initializeUniformityInfoWrapperPassPass(*PassRegistry::getPassRegistry()); 149475ce4c2SSameer Sahasrabuddhe } 150475ce4c2SSameer Sahasrabuddhe 151c76acb9dSJay Foad INITIALIZE_PASS_BEGIN(UniformityInfoWrapperPass, "uniformity", 152c76acb9dSJay Foad "Uniformity Analysis", true, true) 153475ce4c2SSameer Sahasrabuddhe INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) 154f90849dfSpvanhout INITIALIZE_PASS_DEPENDENCY(CycleInfoWrapperPass) 155475ce4c2SSameer Sahasrabuddhe INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) 156c76acb9dSJay Foad INITIALIZE_PASS_END(UniformityInfoWrapperPass, "uniformity", 157c76acb9dSJay Foad "Uniformity Analysis", true, true) 158475ce4c2SSameer Sahasrabuddhe 159475ce4c2SSameer Sahasrabuddhe void UniformityInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { 160475ce4c2SSameer Sahasrabuddhe AU.setPreservesAll(); 161475ce4c2SSameer Sahasrabuddhe AU.addRequired<DominatorTreeWrapperPass>(); 162f90849dfSpvanhout AU.addRequiredTransitive<CycleInfoWrapperPass>(); 163475ce4c2SSameer Sahasrabuddhe AU.addRequired<TargetTransformInfoWrapperPass>(); 164475ce4c2SSameer Sahasrabuddhe } 165475ce4c2SSameer Sahasrabuddhe 166475ce4c2SSameer Sahasrabuddhe bool UniformityInfoWrapperPass::runOnFunction(Function &F) { 167475ce4c2SSameer Sahasrabuddhe auto &cycleInfo = getAnalysis<CycleInfoWrapperPass>().getResult(); 168475ce4c2SSameer Sahasrabuddhe auto &domTree = getAnalysis<DominatorTreeWrapperPass>().getDomTree(); 169475ce4c2SSameer Sahasrabuddhe auto &targetTransformInfo = 170475ce4c2SSameer Sahasrabuddhe getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F); 171475ce4c2SSameer Sahasrabuddhe 172475ce4c2SSameer Sahasrabuddhe m_function = &F; 173*b14e30f1SSameer Sahasrabuddhe m_uniformityInfo = UniformityInfo{domTree, cycleInfo, &targetTransformInfo}; 174d61cba6dSMatt Arsenault 175d61cba6dSMatt Arsenault // Skip computation if we can assume everything is uniform. 17653fb907dSMatt Arsenault if (targetTransformInfo.hasBranchDivergence(m_function)) 177d61cba6dSMatt Arsenault m_uniformityInfo.compute(); 178d61cba6dSMatt Arsenault 179475ce4c2SSameer Sahasrabuddhe return false; 180475ce4c2SSameer Sahasrabuddhe } 181475ce4c2SSameer Sahasrabuddhe 182475ce4c2SSameer Sahasrabuddhe void UniformityInfoWrapperPass::print(raw_ostream &OS, const Module *) const { 183475ce4c2SSameer Sahasrabuddhe OS << "UniformityInfo for function '" << m_function->getName() << "':\n"; 184475ce4c2SSameer Sahasrabuddhe } 185475ce4c2SSameer Sahasrabuddhe 186475ce4c2SSameer Sahasrabuddhe void UniformityInfoWrapperPass::releaseMemory() { 187475ce4c2SSameer Sahasrabuddhe m_uniformityInfo = UniformityInfo{}; 188475ce4c2SSameer Sahasrabuddhe m_function = nullptr; 189475ce4c2SSameer Sahasrabuddhe } 190