diff options
author | Max Kazantsev <max.kazantsev@azul.com> | 2018-08-29 10:51:59 +0000 |
---|---|---|
committer | Max Kazantsev <max.kazantsev@azul.com> | 2018-08-29 10:51:59 +0000 |
commit | 8b4ffe66d6e86e6481372ccb57ab4e72751e98cf (patch) | |
tree | 1467caa2dcc57e1ad0b58e1a4b5f1ceb82fa2bba /llvm/lib/Transforms/Utils/GuardUtils.cpp | |
parent | 6b9bf7ecbc152d5941712f967cd93d1c0e2042a7 (diff) | |
download | llvm-8b4ffe66d6e86e6481372ccb57ab4e72751e98cf.zip llvm-8b4ffe66d6e86e6481372ccb57ab4e72751e98cf.tar.gz llvm-8b4ffe66d6e86e6481372ccb57ab4e72751e98cf.tar.bz2 |
[NFC] Factor out guard utility methods into a separate file
This patch creates file GuardUtils which will contain logic for work with guards
that can be shared across different passes.
Differential Revision: https://reviews.llvm.org/D51151
Reviewed By: fedor.sergeev
llvm-svn: 340914
Diffstat (limited to 'llvm/lib/Transforms/Utils/GuardUtils.cpp')
-rw-r--r-- | llvm/lib/Transforms/Utils/GuardUtils.cpp | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/Utils/GuardUtils.cpp b/llvm/lib/Transforms/Utils/GuardUtils.cpp new file mode 100644 index 0000000..08de0a4 --- /dev/null +++ b/llvm/lib/Transforms/Utils/GuardUtils.cpp @@ -0,0 +1,64 @@ +//===-- GuardUtils.cpp - Utils for work with guards -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Utils that are used to perform transformations related to guards and their +// conditions. +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Utils/GuardUtils.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/MDBuilder.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" + +using namespace llvm; + +static cl::opt<uint32_t> PredicatePassBranchWeight( + "guards-predicate-pass-branch-weight", cl::Hidden, cl::init(1 << 20), + cl::desc("The probability of a guard failing is assumed to be the " + "reciprocal of this value (default = 1 << 20)")); + +void llvm::makeGuardControlFlowExplicit(Function *DeoptIntrinsic, + CallInst *Guard) { + OperandBundleDef DeoptOB(*Guard->getOperandBundle(LLVMContext::OB_deopt)); + SmallVector<Value *, 4> Args(std::next(Guard->arg_begin()), Guard->arg_end()); + + auto *CheckBB = Guard->getParent(); + auto *DeoptBlockTerm = + SplitBlockAndInsertIfThen(Guard->getArgOperand(0), Guard, true); + + auto *CheckBI = cast<BranchInst>(CheckBB->getTerminator()); + + // SplitBlockAndInsertIfThen inserts control flow that branches to + // DeoptBlockTerm if the condition is true. We want the opposite. + CheckBI->swapSuccessors(); + + CheckBI->getSuccessor(0)->setName("guarded"); + CheckBI->getSuccessor(1)->setName("deopt"); + + if (auto *MD = Guard->getMetadata(LLVMContext::MD_make_implicit)) + CheckBI->setMetadata(LLVMContext::MD_make_implicit, MD); + + MDBuilder MDB(Guard->getContext()); + CheckBI->setMetadata(LLVMContext::MD_prof, + MDB.createBranchWeights(PredicatePassBranchWeight, 1)); + + IRBuilder<> B(DeoptBlockTerm); + auto *DeoptCall = B.CreateCall(DeoptIntrinsic, Args, {DeoptOB}, ""); + + if (DeoptIntrinsic->getReturnType()->isVoidTy()) { + B.CreateRetVoid(); + } else { + DeoptCall->setName("deoptcall"); + B.CreateRet(DeoptCall); + } + + DeoptCall->setCallingConv(Guard->getCallingConv()); + DeoptBlockTerm->eraseFromParent(); +} |