Index: llvm/trunk/include/llvm/IR/Instruction.h =================================================================== --- llvm/trunk/include/llvm/IR/Instruction.h +++ llvm/trunk/include/llvm/IR/Instruction.h @@ -311,9 +311,6 @@ /// Returns false if no metadata was found. bool extractProfTotalWeight(uint64_t &TotalVal) const; - /// Updates branch_weights metadata by scaling it by \p S / \p T. - void updateProfWeight(uint64_t S, uint64_t T); - /// Sets the branch_weights metadata to \p W for CallInst. void setProfWeight(uint64_t W); Index: llvm/trunk/include/llvm/IR/Instructions.h =================================================================== --- llvm/trunk/include/llvm/IR/Instructions.h +++ llvm/trunk/include/llvm/IR/Instructions.h @@ -1730,6 +1730,9 @@ return isa(V) && classof(cast(V)); } + /// Updates profile metadata by scaling it by \p S / \p T. + void updateProfWeight(uint64_t S, uint64_t T); + private: // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. Index: llvm/trunk/lib/IR/Instruction.cpp =================================================================== --- llvm/trunk/lib/IR/Instruction.cpp +++ llvm/trunk/lib/IR/Instruction.cpp @@ -735,49 +735,6 @@ return New; } -void Instruction::updateProfWeight(uint64_t S, uint64_t T) { - auto *ProfileData = getMetadata(LLVMContext::MD_prof); - if (ProfileData == nullptr) - return; - - auto *ProfDataName = dyn_cast(ProfileData->getOperand(0)); - if (!ProfDataName || (!ProfDataName->getString().equals("branch_weights") && - !ProfDataName->getString().equals("VP"))) - return; - - MDBuilder MDB(getContext()); - SmallVector Vals; - Vals.push_back(ProfileData->getOperand(0)); - APInt APS(128, S), APT(128, T); - if (ProfDataName->getString().equals("branch_weights")) - for (unsigned i = 1; i < ProfileData->getNumOperands(); i++) { - // Using APInt::div may be expensive, but most cases should fit 64 bits. - APInt Val(128, - mdconst::dyn_extract(ProfileData->getOperand(i)) - ->getValue() - .getZExtValue()); - Val *= APS; - Vals.push_back(MDB.createConstant( - ConstantInt::get(Type::getInt64Ty(getContext()), - Val.udiv(APT).getLimitedValue()))); - } - else if (ProfDataName->getString().equals("VP")) - for (unsigned i = 1; i < ProfileData->getNumOperands(); i += 2) { - // The first value is the key of the value profile, which will not change. - Vals.push_back(ProfileData->getOperand(i)); - // Using APInt::div may be expensive, but most cases should fit 64 bits. - APInt Val(128, - mdconst::dyn_extract(ProfileData->getOperand(i + 1)) - ->getValue() - .getZExtValue()); - Val *= APS; - Vals.push_back(MDB.createConstant( - ConstantInt::get(Type::getInt64Ty(getContext()), - Val.udiv(APT).getLimitedValue()))); - } - setMetadata(LLVMContext::MD_prof, MDNode::get(getContext(), Vals)); -} - void Instruction::setProfWeight(uint64_t W) { assert(isa(this) && "Can only set weights for call like instructions"); Index: llvm/trunk/lib/IR/Instructions.cpp =================================================================== --- llvm/trunk/lib/IR/Instructions.cpp +++ llvm/trunk/lib/IR/Instructions.cpp @@ -28,6 +28,7 @@ #include "llvm/IR/Instruction.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/MDBuilder.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" @@ -458,6 +459,49 @@ return NewCI; } +// Update profile weight for call instruction by scaling it using the ratio +// of S/T. The meaning of "branch_weights" meta data for call instruction is +// transfered to represent call count. +void CallInst::updateProfWeight(uint64_t S, uint64_t T) { + auto *ProfileData = getMetadata(LLVMContext::MD_prof); + if (ProfileData == nullptr) + return; + + auto *ProfDataName = dyn_cast(ProfileData->getOperand(0)); + if (!ProfDataName || (!ProfDataName->getString().equals("branch_weights") && + !ProfDataName->getString().equals("VP"))) + return; + + MDBuilder MDB(getContext()); + SmallVector Vals; + Vals.push_back(ProfileData->getOperand(0)); + APInt APS(128, S), APT(128, T); + if (ProfDataName->getString().equals("branch_weights") && + ProfileData->getNumOperands() > 0) { + // Using APInt::div may be expensive, but most cases should fit 64 bits. + APInt Val(128, mdconst::dyn_extract(ProfileData->getOperand(1)) + ->getValue() + .getZExtValue()); + Val *= APS; + Vals.push_back(MDB.createConstant(ConstantInt::get( + Type::getInt64Ty(getContext()), Val.udiv(APT).getLimitedValue()))); + } else if (ProfDataName->getString().equals("VP")) + for (unsigned i = 1; i < ProfileData->getNumOperands(); i += 2) { + // The first value is the key of the value profile, which will not change. + Vals.push_back(ProfileData->getOperand(i)); + // Using APInt::div may be expensive, but most cases should fit 64 bits. + APInt Val(128, + mdconst::dyn_extract(ProfileData->getOperand(i + 1)) + ->getValue() + .getZExtValue()); + Val *= APS; + Vals.push_back(MDB.createConstant( + ConstantInt::get(Type::getInt64Ty(getContext()), + Val.udiv(APT).getLimitedValue()))); + } + setMetadata(LLVMContext::MD_prof, MDNode::get(getContext(), Vals)); +} + /// IsConstantOne - Return true only if val is constant int 1 static bool IsConstantOne(Value *val) { assert(val && "IsConstantOne does not work with nullptr val");