1a812b39eSPaul Kirth //===- ProfDataUtils.cpp - Utility functions for MD_prof Metadata ---------===// 2a812b39eSPaul Kirth // 3a812b39eSPaul Kirth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a812b39eSPaul Kirth // See https://llvm.org/LICENSE.txt for license information. 5a812b39eSPaul Kirth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a812b39eSPaul Kirth // 7a812b39eSPaul Kirth //===----------------------------------------------------------------------===// 8a812b39eSPaul Kirth // 9a812b39eSPaul Kirth // This file implements utilities for working with Profiling Metadata. 10a812b39eSPaul Kirth // 11a812b39eSPaul Kirth //===----------------------------------------------------------------------===// 12a812b39eSPaul Kirth 136047deb7SPaul Kirth #include "llvm/IR/ProfDataUtils.h" 146047deb7SPaul Kirth #include "llvm/ADT/SmallVector.h" 156047deb7SPaul Kirth #include "llvm/ADT/Twine.h" 166047deb7SPaul Kirth #include "llvm/IR/Constants.h" 176047deb7SPaul Kirth #include "llvm/IR/Function.h" 186047deb7SPaul Kirth #include "llvm/IR/Instructions.h" 196047deb7SPaul Kirth #include "llvm/IR/LLVMContext.h" 20cb4627d1SMatthias Braun #include "llvm/IR/MDBuilder.h" 216047deb7SPaul Kirth #include "llvm/IR/Metadata.h" 226047deb7SPaul Kirth #include "llvm/Support/BranchProbability.h" 236047deb7SPaul Kirth #include "llvm/Support/CommandLine.h" 246047deb7SPaul Kirth 256047deb7SPaul Kirth using namespace llvm; 266047deb7SPaul Kirth 276047deb7SPaul Kirth namespace { 286047deb7SPaul Kirth 296047deb7SPaul Kirth // MD_prof nodes have the following layout 306047deb7SPaul Kirth // 316047deb7SPaul Kirth // In general: 326047deb7SPaul Kirth // { String name, Array of i32 } 336047deb7SPaul Kirth // 346047deb7SPaul Kirth // In terms of Types: 356047deb7SPaul Kirth // { MDString, [i32, i32, ...]} 366047deb7SPaul Kirth // 376047deb7SPaul Kirth // Concretely for Branch Weights 386047deb7SPaul Kirth // { "branch_weights", [i32 1, i32 10000]} 396047deb7SPaul Kirth // 406047deb7SPaul Kirth // We maintain some constants here to ensure that we access the branch weights 416047deb7SPaul Kirth // correctly, and can change the behavior in the future if the layout changes 426047deb7SPaul Kirth 436047deb7SPaul Kirth // The index at which the weights vector starts 446047deb7SPaul Kirth constexpr unsigned WeightsIdx = 1; 456047deb7SPaul Kirth 466047deb7SPaul Kirth // the minimum number of operands for MD_prof nodes with branch weights 476047deb7SPaul Kirth constexpr unsigned MinBWOps = 3; 486047deb7SPaul Kirth 496047deb7SPaul Kirth // We may want to add support for other MD_prof types, so provide an abstraction 506047deb7SPaul Kirth // for checking the metadata type. 516047deb7SPaul Kirth bool isTargetMD(const MDNode *ProfData, const char *Name, unsigned MinOps) { 526047deb7SPaul Kirth // TODO: This routine may be simplified if MD_prof used an enum instead of a 536047deb7SPaul Kirth // string to differentiate the types of MD_prof nodes. 546047deb7SPaul Kirth if (!ProfData || !Name || MinOps < 2) 556047deb7SPaul Kirth return false; 566047deb7SPaul Kirth 576047deb7SPaul Kirth unsigned NOps = ProfData->getNumOperands(); 586047deb7SPaul Kirth if (NOps < MinOps) 596047deb7SPaul Kirth return false; 606047deb7SPaul Kirth 616047deb7SPaul Kirth auto *ProfDataName = dyn_cast<MDString>(ProfData->getOperand(0)); 626047deb7SPaul Kirth if (!ProfDataName) 636047deb7SPaul Kirth return false; 646047deb7SPaul Kirth 656047deb7SPaul Kirth return ProfDataName->getString().equals(Name); 666047deb7SPaul Kirth } 676047deb7SPaul Kirth 686047deb7SPaul Kirth } // namespace 696047deb7SPaul Kirth 706047deb7SPaul Kirth namespace llvm { 716047deb7SPaul Kirth 726047deb7SPaul Kirth bool hasProfMD(const Instruction &I) { 738f8cab6bSKazu Hirata return I.hasMetadata(LLVMContext::MD_prof); 746047deb7SPaul Kirth } 756047deb7SPaul Kirth 766047deb7SPaul Kirth bool isBranchWeightMD(const MDNode *ProfileData) { 776047deb7SPaul Kirth return isTargetMD(ProfileData, "branch_weights", MinBWOps); 786047deb7SPaul Kirth } 796047deb7SPaul Kirth 806047deb7SPaul Kirth bool hasBranchWeightMD(const Instruction &I) { 816047deb7SPaul Kirth auto *ProfileData = I.getMetadata(LLVMContext::MD_prof); 826047deb7SPaul Kirth return isBranchWeightMD(ProfileData); 836047deb7SPaul Kirth } 846047deb7SPaul Kirth 85e741b8c2SChristian Ulmann bool hasValidBranchWeightMD(const Instruction &I) { 86e741b8c2SChristian Ulmann return getValidBranchWeightMDNode(I); 87e741b8c2SChristian Ulmann } 88e741b8c2SChristian Ulmann 89e741b8c2SChristian Ulmann MDNode *getBranchWeightMDNode(const Instruction &I) { 90e741b8c2SChristian Ulmann auto *ProfileData = I.getMetadata(LLVMContext::MD_prof); 91e741b8c2SChristian Ulmann if (!isBranchWeightMD(ProfileData)) 92e741b8c2SChristian Ulmann return nullptr; 93e741b8c2SChristian Ulmann return ProfileData; 94e741b8c2SChristian Ulmann } 95e741b8c2SChristian Ulmann 96e741b8c2SChristian Ulmann MDNode *getValidBranchWeightMDNode(const Instruction &I) { 97e741b8c2SChristian Ulmann auto *ProfileData = getBranchWeightMDNode(I); 98e741b8c2SChristian Ulmann if (ProfileData && ProfileData->getNumOperands() == 1 + I.getNumSuccessors()) 99e741b8c2SChristian Ulmann return ProfileData; 100e741b8c2SChristian Ulmann return nullptr; 101e741b8c2SChristian Ulmann } 102e741b8c2SChristian Ulmann 103285e0235SMatthias Braun void extractFromBranchWeightMD(const MDNode *ProfileData, 104285e0235SMatthias Braun SmallVectorImpl<uint32_t> &Weights) { 105285e0235SMatthias Braun assert(isBranchWeightMD(ProfileData) && "wrong metadata"); 106285e0235SMatthias Braun 107285e0235SMatthias Braun unsigned NOps = ProfileData->getNumOperands(); 108285e0235SMatthias Braun assert(WeightsIdx < NOps && "Weights Index must be less than NOps."); 109285e0235SMatthias Braun Weights.resize(NOps - WeightsIdx); 110285e0235SMatthias Braun 111285e0235SMatthias Braun for (unsigned Idx = WeightsIdx, E = NOps; Idx != E; ++Idx) { 112285e0235SMatthias Braun ConstantInt *Weight = 113285e0235SMatthias Braun mdconst::dyn_extract<ConstantInt>(ProfileData->getOperand(Idx)); 114285e0235SMatthias Braun assert(Weight && "Malformed branch_weight in MD_prof node"); 115285e0235SMatthias Braun assert(Weight->getValue().getActiveBits() <= 32 && 116285e0235SMatthias Braun "Too many bits for uint32_t"); 117285e0235SMatthias Braun Weights[Idx - WeightsIdx] = Weight->getZExtValue(); 118285e0235SMatthias Braun } 119285e0235SMatthias Braun } 120285e0235SMatthias Braun 1216047deb7SPaul Kirth bool extractBranchWeights(const MDNode *ProfileData, 1226047deb7SPaul Kirth SmallVectorImpl<uint32_t> &Weights) { 1236047deb7SPaul Kirth if (!isBranchWeightMD(ProfileData)) 1246047deb7SPaul Kirth return false; 125285e0235SMatthias Braun extractFromBranchWeightMD(ProfileData, Weights); 126285e0235SMatthias Braun return true; 1276047deb7SPaul Kirth } 1286047deb7SPaul Kirth 1296047deb7SPaul Kirth bool extractBranchWeights(const Instruction &I, 1306047deb7SPaul Kirth SmallVectorImpl<uint32_t> &Weights) { 1316047deb7SPaul Kirth auto *ProfileData = I.getMetadata(LLVMContext::MD_prof); 1326047deb7SPaul Kirth return extractBranchWeights(ProfileData, Weights); 1336047deb7SPaul Kirth } 1346047deb7SPaul Kirth 1356047deb7SPaul Kirth bool extractBranchWeights(const Instruction &I, uint64_t &TrueVal, 1366047deb7SPaul Kirth uint64_t &FalseVal) { 1376047deb7SPaul Kirth assert((I.getOpcode() == Instruction::Br || 1386047deb7SPaul Kirth I.getOpcode() == Instruction::Select) && 139e741b8c2SChristian Ulmann "Looking for branch weights on something besides branch, select, or " 140e741b8c2SChristian Ulmann "switch"); 1416047deb7SPaul Kirth 1426047deb7SPaul Kirth SmallVector<uint32_t, 2> Weights; 1436047deb7SPaul Kirth auto *ProfileData = I.getMetadata(LLVMContext::MD_prof); 1446047deb7SPaul Kirth if (!extractBranchWeights(ProfileData, Weights)) 1456047deb7SPaul Kirth return false; 1466047deb7SPaul Kirth 1476047deb7SPaul Kirth if (Weights.size() > 2) 1486047deb7SPaul Kirth return false; 1496047deb7SPaul Kirth 1506047deb7SPaul Kirth TrueVal = Weights[0]; 1516047deb7SPaul Kirth FalseVal = Weights[1]; 1526047deb7SPaul Kirth return true; 1536047deb7SPaul Kirth } 1546047deb7SPaul Kirth 1556047deb7SPaul Kirth bool extractProfTotalWeight(const MDNode *ProfileData, uint64_t &TotalVal) { 1566047deb7SPaul Kirth TotalVal = 0; 1576047deb7SPaul Kirth if (!ProfileData) 1586047deb7SPaul Kirth return false; 1596047deb7SPaul Kirth 1606047deb7SPaul Kirth auto *ProfDataName = dyn_cast<MDString>(ProfileData->getOperand(0)); 1616047deb7SPaul Kirth if (!ProfDataName) 1626047deb7SPaul Kirth return false; 1636047deb7SPaul Kirth 1646047deb7SPaul Kirth if (ProfDataName->getString().equals("branch_weights")) { 165*6ce03ff3SShubham Sandeep Rastogi for (unsigned Idx = 1; Idx < ProfileData->getNumOperands(); Idx++) { 166*6ce03ff3SShubham Sandeep Rastogi auto *V = mdconst::dyn_extract<ConstantInt>(ProfileData->getOperand(Idx)); 1676047deb7SPaul Kirth assert(V && "Malformed branch_weight in MD_prof node"); 1686047deb7SPaul Kirth TotalVal += V->getValue().getZExtValue(); 1696047deb7SPaul Kirth } 1706047deb7SPaul Kirth return true; 171deef5b8cSPaul Kirth } 172deef5b8cSPaul Kirth 173deef5b8cSPaul Kirth if (ProfDataName->getString().equals("VP") && 1746047deb7SPaul Kirth ProfileData->getNumOperands() > 3) { 1756047deb7SPaul Kirth TotalVal = mdconst::dyn_extract<ConstantInt>(ProfileData->getOperand(2)) 1766047deb7SPaul Kirth ->getValue() 1776047deb7SPaul Kirth .getZExtValue(); 1786047deb7SPaul Kirth return true; 1796047deb7SPaul Kirth } 1806047deb7SPaul Kirth return false; 1816047deb7SPaul Kirth } 1826047deb7SPaul Kirth 183e741b8c2SChristian Ulmann bool extractProfTotalWeight(const Instruction &I, uint64_t &TotalVal) { 184e741b8c2SChristian Ulmann return extractProfTotalWeight(I.getMetadata(LLVMContext::MD_prof), TotalVal); 185e741b8c2SChristian Ulmann } 186e741b8c2SChristian Ulmann 187cb4627d1SMatthias Braun void setBranchWeights(Instruction &I, ArrayRef<uint32_t> Weights) { 188cb4627d1SMatthias Braun MDBuilder MDB(I.getContext()); 189cb4627d1SMatthias Braun MDNode *BranchWeights = MDB.createBranchWeights(Weights); 190cb4627d1SMatthias Braun I.setMetadata(LLVMContext::MD_prof, BranchWeights); 191cb4627d1SMatthias Braun } 192cb4627d1SMatthias Braun 1936047deb7SPaul Kirth } // namespace llvm 194