65 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			65 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===-- 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();
 | |
| }
 |