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 12 #include "llvm/Transforms/Utils/GuardUtils.h" 13 #include "llvm/Analysis/GuardUtils.h" 14 #include "llvm/IR/Function.h" 15 #include "llvm/IR/IRBuilder.h" 16 #include "llvm/IR/Instructions.h" 17 #include "llvm/IR/MDBuilder.h" 18 #include "llvm/IR/PatternMatch.h" 19 #include "llvm/Support/CommandLine.h" 20 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 21 22 using namespace llvm; 23 using namespace llvm::PatternMatch; 24 25 static cl::opt<uint32_t> PredicatePassBranchWeight( 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 30 void llvm::makeGuardControlFlowExplicit(Function *DeoptIntrinsic, 31 CallInst *Guard, bool UseWC) { 32 OperandBundleDef DeoptOB(*Guard->getOperandBundle(LLVMContext::OB_deopt)); 33 SmallVector<Value *, 4> Args(drop_begin(Guard->args())); 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, 53 MDB.createBranchWeights(PredicatePassBranchWeight, 1)); 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 82 void 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 108 void 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 } 127