LLVM 17.0.0git
GuardUtils.cpp
Go to the documentation of this file.
1//===-- GuardUtils.cpp - Utils for work with guards -------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8// Utils that are used to perform transformations related to guards and their
9// conditions.
10//===----------------------------------------------------------------------===//
11
14#include "llvm/IR/Function.h"
15#include "llvm/IR/IRBuilder.h"
17#include "llvm/IR/MDBuilder.h"
21
22using namespace llvm;
23using namespace llvm::PatternMatch;
24
26 "guards-predicate-pass-branch-weight", cl::Hidden, cl::init(1 << 20),
27 cl::desc("The probability of a guard failing is assumed to be the "
28 "reciprocal of this value (default = 1 << 20)"));
29
31 CallInst *Guard, bool UseWC) {
34
35 auto *CheckBB = Guard->getParent();
36 auto *DeoptBlockTerm =
37 SplitBlockAndInsertIfThen(Guard->getArgOperand(0), Guard, true);
38
39 auto *CheckBI = cast<BranchInst>(CheckBB->getTerminator());
40
41 // SplitBlockAndInsertIfThen inserts control flow that branches to
42 // DeoptBlockTerm if the condition is true. We want the opposite.
43 CheckBI->swapSuccessors();
44
45 CheckBI->getSuccessor(0)->setName("guarded");
46 CheckBI->getSuccessor(1)->setName("deopt");
47
48 if (auto *MD = Guard->getMetadata(LLVMContext::MD_make_implicit))
49 CheckBI->setMetadata(LLVMContext::MD_make_implicit, MD);
50
51 MDBuilder MDB(Guard->getContext());
52 CheckBI->setMetadata(LLVMContext::MD_prof,
54
55 IRBuilder<> B(DeoptBlockTerm);
56 auto *DeoptCall = B.CreateCall(DeoptIntrinsic, Args, {DeoptOB}, "");
57
58 if (DeoptIntrinsic->getReturnType()->isVoidTy()) {
59 B.CreateRetVoid();
60 } else {
61 DeoptCall->setName("deoptcall");
62 B.CreateRet(DeoptCall);
63 }
64
65 DeoptCall->setCallingConv(Guard->getCallingConv());
66 DeoptBlockTerm->eraseFromParent();
67
68 if (UseWC) {
69 // We want the guard to be expressed as explicit control flow, but still be
70 // widenable. For that, we add Widenable Condition intrinsic call to the
71 // guard's condition.
72 IRBuilder<> B(CheckBI);
73 auto *WC = B.CreateIntrinsic(Intrinsic::experimental_widenable_condition,
74 {}, {}, nullptr, "widenable_cond");
75 CheckBI->setCondition(B.CreateAnd(CheckBI->getCondition(), WC,
76 "exiplicit_guard_cond"));
77 assert(isWidenableBranch(CheckBI) && "Branch must be widenable.");
78 }
79}
80
81
82void llvm::widenWidenableBranch(BranchInst *WidenableBR, Value *NewCond) {
83 assert(isWidenableBranch(WidenableBR) && "precondition");
84
85 // The tempting trivially option is to produce something like this:
86 // br (and oldcond, newcond) where oldcond is assumed to contain a widenable
87 // condition, but that doesn't match the pattern parseWidenableBranch expects
88 // so we have to be more sophisticated.
89
90 Use *C, *WC;
91 BasicBlock *IfTrueBB, *IfFalseBB;
92 parseWidenableBranch(WidenableBR, C, WC, IfTrueBB, IfFalseBB);
93 if (!C) {
94 // br (wc()), ... form
95 IRBuilder<> B(WidenableBR);
96 WidenableBR->setCondition(B.CreateAnd(NewCond, WC->get()));
97 } else {
98 // br (wc & C), ... form
99 IRBuilder<> B(WidenableBR);
100 C->set(B.CreateAnd(NewCond, C->get()));
101 Instruction *WCAnd = cast<Instruction>(WidenableBR->getCondition());
102 // Condition is only guaranteed to dominate branch
103 WCAnd->moveBefore(WidenableBR);
104 }
105 assert(isWidenableBranch(WidenableBR) && "preserve widenabiliy");
106}
107
108void llvm::setWidenableBranchCond(BranchInst *WidenableBR, Value *NewCond) {
109 assert(isWidenableBranch(WidenableBR) && "precondition");
110
111 Use *C, *WC;
112 BasicBlock *IfTrueBB, *IfFalseBB;
113 parseWidenableBranch(WidenableBR, C, WC, IfTrueBB, IfFalseBB);
114 if (!C) {
115 // br (wc()), ... form
116 IRBuilder<> B(WidenableBR);
117 WidenableBR->setCondition(B.CreateAnd(NewCond, WC->get()));
118 } else {
119 // br (wc & C), ... form
120 Instruction *WCAnd = cast<Instruction>(WidenableBR->getCondition());
121 // Condition is only guaranteed to dominate branch
122 WCAnd->moveBefore(WidenableBR);
123 C->set(NewCond);
124 }
125 assert(isWidenableBranch(WidenableBR) && "preserve widenabiliy");
126}
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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)"))
LLVM Basic Block Representation.
Definition: BasicBlock.h:56
Conditional or Unconditional Branch instruction.
void setCondition(Value *V)
Value * getCondition() const
std::optional< OperandBundleUse > getOperandBundle(StringRef Name) const
Return an operand bundle by name, if present.
Definition: InstrTypes.h:2036
CallingConv::ID getCallingConv() const
Definition: InstrTypes.h:1465
Value * getArgOperand(unsigned i) const
Definition: InstrTypes.h:1351
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
Definition: InstrTypes.h:1342
This class represents a function call, abstracting a target machine's calling convention.
Type * getReturnType() const
Returns the type of the ret val.
Definition: Function.h:179
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:2550
const BasicBlock * getParent() const
Definition: Instruction.h:90
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
Definition: Instruction.h:275
void moveBefore(Instruction *MovePos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
MDNode * createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight)
Return metadata containing two branch weights.
Definition: MDBuilder.cpp:37
A container for an operand bundle being viewed as a set of values rather than a set of uses.
Definition: InstrTypes.h:1137
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
bool isVoidTy() const
Return true if this is 'void'.
Definition: Type.h:140
A Use represents the edge between a Value definition and its users.
Definition: Use.h:43
LLVM Value Representation.
Definition: Value.h:74
LLVMContext & getContext() const
All values hold a context through their type.
Definition: Value.cpp:994
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:445
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition: STLExtras.h:386
void makeGuardControlFlowExplicit(Function *DeoptIntrinsic, CallInst *Guard, bool UseWC)
Splits control flow at point of Guard, replacing it with explicit branch by the condition of guard's ...
Definition: GuardUtils.cpp:30
void widenWidenableBranch(BranchInst *WidenableBR, Value *NewCond)
Given a branch we know is widenable (defined per Analysis/GuardUtils.h), widen it such that condition...
Definition: GuardUtils.cpp:82
void setWidenableBranchCond(BranchInst *WidenableBR, Value *Cond)
Given a branch we know is widenable (defined per Analysis/GuardUtils.h), set it's condition such that...
Definition: GuardUtils.cpp:108
bool parseWidenableBranch(const User *U, Value *&Condition, Value *&WidenableCondition, BasicBlock *&IfTrueBB, BasicBlock *&IfFalseBB)
If U is widenable branch looking like: cond = ... wc = call i1 @llvm.experimental....
Definition: GuardUtils.cpp:44
bool isWidenableBranch(const User *U)
Returns true iff U is a widenable branch (that is, parseWidenableBranch returns true).
Definition: GuardUtils.cpp:22
Instruction * SplitBlockAndInsertIfThen(Value *Cond, Instruction *SplitBefore, bool Unreachable, MDNode *BranchWeights, DominatorTree *DT, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...