diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:12 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:12 +0000 |
commit | e6d1592492a3a379186bfb02bd0f4eda0669c0d5 (patch) | |
tree | 599ab169a01f1c86eda9adc774edaedde2f2db5b /lib/IR/Instructions.cpp | |
parent | 1a56a5ead7a2e84bee8240f5f6b033b5f1707154 (diff) |
Diffstat (limited to 'lib/IR/Instructions.cpp')
-rw-r--r-- | lib/IR/Instructions.cpp | 341 |
1 files changed, 323 insertions, 18 deletions
diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp index 06b46724a87f..2e7cad103c12 100644 --- a/lib/IR/Instructions.cpp +++ b/lib/IR/Instructions.cpp @@ -1,9 +1,8 @@ //===- Instructions.cpp - Implement the LLVM instructions -----------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -29,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" @@ -45,6 +45,12 @@ using namespace llvm; +static cl::opt<bool> SwitchInstProfUpdateWrapperStrict( + "switch-inst-prof-update-wrapper-strict", cl::Hidden, + cl::desc("Assert that prof branch_weights metadata is valid when creating " + "an instance of SwitchInstProfUpdateWrapper"), + cl::init(false)); + //===----------------------------------------------------------------------===// // AllocaInst Class //===----------------------------------------------------------------------===// @@ -257,6 +263,11 @@ void LandingPadInst::addClause(Constant *Val) { Function *CallBase::getCaller() { return getParent()->getParent(); } +unsigned CallBase::getNumSubclassExtraOperandsDynamic() const { + assert(getOpcode() == Instruction::CallBr && "Unexpected opcode!"); + return cast<CallBrInst>(this)->getNumIndirectDests() + 1; +} + bool CallBase::isIndirectCall() const { const Value *V = getCalledValue(); if (isa<Function>(V) || isa<Constant>(V)) @@ -267,6 +278,21 @@ bool CallBase::isIndirectCall() const { return true; } +/// Tests if this call site must be tail call optimized. Only a CallInst can +/// be tail call optimized. +bool CallBase::isMustTailCall() const { + if (auto *CI = dyn_cast<CallInst>(this)) + return CI->isMustTailCall(); + return false; +} + +/// Tests if this call site is marked as a tail call. +bool CallBase::isTailCall() const { + if (auto *CI = dyn_cast<CallInst>(this)) + return CI->isTailCall(); + return false; +} + Intrinsic::ID CallBase::getIntrinsicID() const { if (auto *F = getCalledFunction()) return F->getIntrinsicID(); @@ -429,8 +455,8 @@ CallInst *CallInst::Create(CallInst *CI, ArrayRef<OperandBundleDef> OpB, Instruction *InsertPt) { std::vector<Value *> Args(CI->arg_begin(), CI->arg_end()); - auto *NewCI = CallInst::Create(CI->getCalledValue(), Args, OpB, CI->getName(), - InsertPt); + auto *NewCI = CallInst::Create(CI->getFunctionType(), CI->getCalledValue(), + Args, OpB, CI->getName(), InsertPt); NewCI->setTailCallKind(CI->getTailCallKind()); NewCI->setCallingConv(CI->getCallingConv()); NewCI->SubclassOptionalData = CI->SubclassOptionalData; @@ -439,14 +465,57 @@ CallInst *CallInst::Create(CallInst *CI, ArrayRef<OperandBundleDef> OpB, 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<MDString>(ProfileData->getOperand(0)); + if (!ProfDataName || (!ProfDataName->getString().equals("branch_weights") && + !ProfDataName->getString().equals("VP"))) + return; + if (T == 0) { + LLVM_DEBUG(dbgs() << "Attempting to update profile weights will result in " + "div by 0. Ignoring. Likely the function " + << getParent()->getParent()->getName() + << " has 0 entry count, and contains call instructions " + "with non-zero prof info."); + return; + } - - - - - + MDBuilder MDB(getContext()); + SmallVector<Metadata *, 3> 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<ConstantInt>(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<ConstantInt>(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) { @@ -503,7 +572,7 @@ static Instruction *createMalloc(Instruction *InsertBefore, BasicBlock *BB = InsertBefore ? InsertBefore->getParent() : InsertAtEnd; Module *M = BB->getParent()->getParent(); Type *BPTy = Type::getInt8PtrTy(BB->getContext()); - Value *MallocFunc = MallocF; + FunctionCallee MallocFunc = MallocF; if (!MallocFunc) // prototype malloc as "void *malloc(size_t)" MallocFunc = M->getOrInsertFunction("malloc", BPTy, IntPtrTy); @@ -527,7 +596,7 @@ static Instruction *createMalloc(Instruction *InsertBefore, } } MCall->setTailCall(); - if (Function *F = dyn_cast<Function>(MallocFunc)) { + if (Function *F = dyn_cast<Function>(MallocFunc.getCallee())) { MCall->setCallingConv(F->getCallingConv()); if (!F->returnDoesNotAlias()) F->setReturnDoesNotAlias(); @@ -600,7 +669,7 @@ static Instruction *createFree(Value *Source, Type *VoidTy = Type::getVoidTy(M->getContext()); Type *IntPtrTy = Type::getInt8PtrTy(M->getContext()); // prototype free as "void free(void*)" - Value *FreeFunc = M->getOrInsertFunction("free", VoidTy, IntPtrTy); + FunctionCallee FreeFunc = M->getOrInsertFunction("free", VoidTy, IntPtrTy); CallInst *Result = nullptr; Value *PtrCast = Source; if (InsertBefore) { @@ -613,7 +682,7 @@ static Instruction *createFree(Value *Source, Result = CallInst::Create(FreeFunc, PtrCast, Bundles, ""); } Result->setTailCall(); - if (Function *F = dyn_cast<Function>(FreeFunc)) + if (Function *F = dyn_cast<Function>(FreeFunc.getCallee())) Result->setCallingConv(F->getCallingConv()); return Result; @@ -697,9 +766,9 @@ InvokeInst *InvokeInst::Create(InvokeInst *II, ArrayRef<OperandBundleDef> OpB, Instruction *InsertPt) { std::vector<Value *> Args(II->arg_begin(), II->arg_end()); - auto *NewII = InvokeInst::Create(II->getCalledValue(), II->getNormalDest(), - II->getUnwindDest(), Args, OpB, - II->getName(), InsertPt); + auto *NewII = InvokeInst::Create(II->getFunctionType(), II->getCalledValue(), + II->getNormalDest(), II->getUnwindDest(), + Args, OpB, II->getName(), InsertPt); NewII->setCallingConv(II->getCallingConv()); NewII->SubclassOptionalData = II->SubclassOptionalData; NewII->setAttributes(II->getAttributes()); @@ -713,6 +782,76 @@ LandingPadInst *InvokeInst::getLandingPadInst() const { } //===----------------------------------------------------------------------===// +// CallBrInst Implementation +//===----------------------------------------------------------------------===// + +void CallBrInst::init(FunctionType *FTy, Value *Fn, BasicBlock *Fallthrough, + ArrayRef<BasicBlock *> IndirectDests, + ArrayRef<Value *> Args, + ArrayRef<OperandBundleDef> Bundles, + const Twine &NameStr) { + this->FTy = FTy; + + assert((int)getNumOperands() == + ComputeNumOperands(Args.size(), IndirectDests.size(), + CountBundleInputs(Bundles)) && + "NumOperands not set up?"); + NumIndirectDests = IndirectDests.size(); + setDefaultDest(Fallthrough); + for (unsigned i = 0; i != NumIndirectDests; ++i) + setIndirectDest(i, IndirectDests[i]); + setCalledOperand(Fn); + +#ifndef NDEBUG + assert(((Args.size() == FTy->getNumParams()) || + (FTy->isVarArg() && Args.size() > FTy->getNumParams())) && + "Calling a function with bad signature"); + + for (unsigned i = 0, e = Args.size(); i != e; i++) + assert((i >= FTy->getNumParams() || + FTy->getParamType(i) == Args[i]->getType()) && + "Calling a function with a bad signature!"); +#endif + + std::copy(Args.begin(), Args.end(), op_begin()); + + auto It = populateBundleOperandInfos(Bundles, Args.size()); + (void)It; + assert(It + 2 + IndirectDests.size() == op_end() && "Should add up!"); + + setName(NameStr); +} + +CallBrInst::CallBrInst(const CallBrInst &CBI) + : CallBase(CBI.Attrs, CBI.FTy, CBI.getType(), Instruction::CallBr, + OperandTraits<CallBase>::op_end(this) - CBI.getNumOperands(), + CBI.getNumOperands()) { + setCallingConv(CBI.getCallingConv()); + std::copy(CBI.op_begin(), CBI.op_end(), op_begin()); + std::copy(CBI.bundle_op_info_begin(), CBI.bundle_op_info_end(), + bundle_op_info_begin()); + SubclassOptionalData = CBI.SubclassOptionalData; + NumIndirectDests = CBI.NumIndirectDests; +} + +CallBrInst *CallBrInst::Create(CallBrInst *CBI, ArrayRef<OperandBundleDef> OpB, + Instruction *InsertPt) { + std::vector<Value *> Args(CBI->arg_begin(), CBI->arg_end()); + + auto *NewCBI = CallBrInst::Create(CBI->getFunctionType(), + CBI->getCalledValue(), + CBI->getDefaultDest(), + CBI->getIndirectDests(), + Args, OpB, CBI->getName(), InsertPt); + NewCBI->setCallingConv(CBI->getCallingConv()); + NewCBI->SubclassOptionalData = CBI->SubclassOptionalData; + NewCBI->setAttributes(CBI->getAttributes()); + NewCBI->setDebugLoc(CBI->getDebugLoc()); + NewCBI->NumIndirectDests = CBI->NumIndirectDests; + return NewCBI; +} + +//===----------------------------------------------------------------------===// // ReturnInst Implementation //===----------------------------------------------------------------------===// @@ -1408,6 +1547,10 @@ StringRef AtomicRMWInst::getOperationName(BinOp Op) { return "umax"; case AtomicRMWInst::UMin: return "umin"; + case AtomicRMWInst::FAdd: + return "fadd"; + case AtomicRMWInst::FSub: + return "fsub"; case AtomicRMWInst::BAD_BINOP: return "<invalid operation>"; } @@ -1666,6 +1809,25 @@ ShuffleVectorInst::ShuffleVectorInst(Value *V1, Value *V2, Value *Mask, setName(Name); } +void ShuffleVectorInst::commute() { + int NumOpElts = Op<0>()->getType()->getVectorNumElements(); + int NumMaskElts = getMask()->getType()->getVectorNumElements(); + SmallVector<Constant*, 16> NewMask(NumMaskElts); + Type *Int32Ty = Type::getInt32Ty(getContext()); + for (int i = 0; i != NumMaskElts; ++i) { + int MaskElt = getMaskValue(i); + if (MaskElt == -1) { + NewMask[i] = UndefValue::get(Int32Ty); + continue; + } + assert(MaskElt >= 0 && MaskElt < 2 * NumOpElts && "Out-of-range mask"); + MaskElt = (MaskElt < NumOpElts) ? MaskElt + NumOpElts : MaskElt - NumOpElts; + NewMask[i] = ConstantInt::get(Int32Ty, MaskElt); + } + Op<2>() = ConstantVector::get(NewMask); + Op<0>().swap(Op<1>()); +} + bool ShuffleVectorInst::isValidOperands(const Value *V1, const Value *V2, const Value *Mask) { // V1 and V2 must be vectors of the same type. @@ -3714,6 +3876,141 @@ void SwitchInst::growOperands() { growHungoffUses(ReservedSpace); } +MDNode * +SwitchInstProfUpdateWrapper::getProfBranchWeightsMD(const SwitchInst &SI) { + if (MDNode *ProfileData = SI.getMetadata(LLVMContext::MD_prof)) + if (auto *MDName = dyn_cast<MDString>(ProfileData->getOperand(0))) + if (MDName->getString() == "branch_weights") + return ProfileData; + return nullptr; +} + +MDNode *SwitchInstProfUpdateWrapper::buildProfBranchWeightsMD() { + assert(State == Changed && "called only if metadata has changed"); + + if (!Weights) + return nullptr; + + assert(SI.getNumSuccessors() == Weights->size() && + "num of prof branch_weights must accord with num of successors"); + + bool AllZeroes = + all_of(Weights.getValue(), [](uint32_t W) { return W == 0; }); + + if (AllZeroes || Weights.getValue().size() < 2) + return nullptr; + + return MDBuilder(SI.getParent()->getContext()).createBranchWeights(*Weights); +} + +void SwitchInstProfUpdateWrapper::init() { + MDNode *ProfileData = getProfBranchWeightsMD(SI); + if (!ProfileData) { + State = Initialized; + return; + } + + if (ProfileData->getNumOperands() != SI.getNumSuccessors() + 1) { + State = Invalid; + if (SwitchInstProfUpdateWrapperStrict) + llvm_unreachable("number of prof branch_weights metadata operands does " + "not correspond to number of succesors"); + return; + } + + SmallVector<uint32_t, 8> Weights; + for (unsigned CI = 1, CE = SI.getNumSuccessors(); CI <= CE; ++CI) { + ConstantInt *C = mdconst::extract<ConstantInt>(ProfileData->getOperand(CI)); + uint32_t CW = C->getValue().getZExtValue(); + Weights.push_back(CW); + } + State = Initialized; + this->Weights = std::move(Weights); +} + +SwitchInst::CaseIt +SwitchInstProfUpdateWrapper::removeCase(SwitchInst::CaseIt I) { + if (Weights) { + assert(SI.getNumSuccessors() == Weights->size() && + "num of prof branch_weights must accord with num of successors"); + State = Changed; + // Copy the last case to the place of the removed one and shrink. + // This is tightly coupled with the way SwitchInst::removeCase() removes + // the cases in SwitchInst::removeCase(CaseIt). + Weights.getValue()[I->getCaseIndex() + 1] = Weights.getValue().back(); + Weights.getValue().pop_back(); + } + return SI.removeCase(I); +} + +void SwitchInstProfUpdateWrapper::addCase( + ConstantInt *OnVal, BasicBlock *Dest, + SwitchInstProfUpdateWrapper::CaseWeightOpt W) { + SI.addCase(OnVal, Dest); + + if (State == Invalid) + return; + + if (!Weights && W && *W) { + State = Changed; + Weights = SmallVector<uint32_t, 8>(SI.getNumSuccessors(), 0); + Weights.getValue()[SI.getNumSuccessors() - 1] = *W; + } else if (Weights) { + State = Changed; + Weights.getValue().push_back(W ? *W : 0); + } + if (Weights) + assert(SI.getNumSuccessors() == Weights->size() && + "num of prof branch_weights must accord with num of successors"); +} + +SymbolTableList<Instruction>::iterator +SwitchInstProfUpdateWrapper::eraseFromParent() { + // Instruction is erased. Mark as unchanged to not touch it in the destructor. + if (State != Invalid) { + State = Initialized; + if (Weights) + Weights->resize(0); + } + return SI.eraseFromParent(); +} + +SwitchInstProfUpdateWrapper::CaseWeightOpt +SwitchInstProfUpdateWrapper::getSuccessorWeight(unsigned idx) { + if (!Weights) + return None; + return Weights.getValue()[idx]; +} + +void SwitchInstProfUpdateWrapper::setSuccessorWeight( + unsigned idx, SwitchInstProfUpdateWrapper::CaseWeightOpt W) { + if (!W || State == Invalid) + return; + + if (!Weights && *W) + Weights = SmallVector<uint32_t, 8>(SI.getNumSuccessors(), 0); + + if (Weights) { + auto &OldW = Weights.getValue()[idx]; + if (*W != OldW) { + State = Changed; + OldW = *W; + } + } +} + +SwitchInstProfUpdateWrapper::CaseWeightOpt +SwitchInstProfUpdateWrapper::getSuccessorWeight(const SwitchInst &SI, + unsigned idx) { + if (MDNode *ProfileData = getProfBranchWeightsMD(SI)) + if (ProfileData->getNumOperands() == SI.getNumSuccessors() + 1) + return mdconst::extract<ConstantInt>(ProfileData->getOperand(idx + 1)) + ->getValue() + .getZExtValue(); + + return None; +} + //===----------------------------------------------------------------------===// // IndirectBrInst Implementation //===----------------------------------------------------------------------===// @@ -3978,6 +4275,14 @@ InvokeInst *InvokeInst::cloneImpl() const { return new(getNumOperands()) InvokeInst(*this); } +CallBrInst *CallBrInst::cloneImpl() const { + if (hasOperandBundles()) { + unsigned DescriptorBytes = getNumOperandBundles() * sizeof(BundleOpInfo); + return new (getNumOperands(), DescriptorBytes) CallBrInst(*this); + } + return new (getNumOperands()) CallBrInst(*this); +} + ResumeInst *ResumeInst::cloneImpl() const { return new (1) ResumeInst(*this); } CleanupReturnInst *CleanupReturnInst::cloneImpl() const { |