1343171Sdim//===-- GuardUtils.cpp - Utils for work with guards -------------*- C++ -*-===// 2343171Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6343171Sdim// 7343171Sdim//===----------------------------------------------------------------------===// 8343171Sdim// Utils that are used to perform transformations related to guards and their 9343171Sdim// conditions. 10343171Sdim//===----------------------------------------------------------------------===// 11343171Sdim 12343171Sdim#include "llvm/Transforms/Utils/GuardUtils.h" 13360784Sdim#include "llvm/Analysis/GuardUtils.h" 14343171Sdim#include "llvm/IR/Function.h" 15360784Sdim#include "llvm/IR/IRBuilder.h" 16343171Sdim#include "llvm/IR/Instructions.h" 17343171Sdim#include "llvm/IR/MDBuilder.h" 18360784Sdim#include "llvm/IR/PatternMatch.h" 19360784Sdim#include "llvm/Support/CommandLine.h" 20343171Sdim#include "llvm/Transforms/Utils/BasicBlockUtils.h" 21343171Sdim 22343171Sdimusing namespace llvm; 23360784Sdimusing namespace llvm::PatternMatch; 24343171Sdim 25343171Sdimstatic cl::opt<uint32_t> PredicatePassBranchWeight( 26343171Sdim "guards-predicate-pass-branch-weight", cl::Hidden, cl::init(1 << 20), 27343171Sdim cl::desc("The probability of a guard failing is assumed to be the " 28343171Sdim "reciprocal of this value (default = 1 << 20)")); 29343171Sdim 30343171Sdimvoid llvm::makeGuardControlFlowExplicit(Function *DeoptIntrinsic, 31360784Sdim CallInst *Guard, bool UseWC) { 32343171Sdim OperandBundleDef DeoptOB(*Guard->getOperandBundle(LLVMContext::OB_deopt)); 33343171Sdim SmallVector<Value *, 4> Args(std::next(Guard->arg_begin()), Guard->arg_end()); 34343171Sdim 35343171Sdim auto *CheckBB = Guard->getParent(); 36343171Sdim auto *DeoptBlockTerm = 37343171Sdim SplitBlockAndInsertIfThen(Guard->getArgOperand(0), Guard, true); 38343171Sdim 39343171Sdim auto *CheckBI = cast<BranchInst>(CheckBB->getTerminator()); 40343171Sdim 41343171Sdim // SplitBlockAndInsertIfThen inserts control flow that branches to 42343171Sdim // DeoptBlockTerm if the condition is true. We want the opposite. 43343171Sdim CheckBI->swapSuccessors(); 44343171Sdim 45343171Sdim CheckBI->getSuccessor(0)->setName("guarded"); 46343171Sdim CheckBI->getSuccessor(1)->setName("deopt"); 47343171Sdim 48343171Sdim if (auto *MD = Guard->getMetadata(LLVMContext::MD_make_implicit)) 49343171Sdim CheckBI->setMetadata(LLVMContext::MD_make_implicit, MD); 50343171Sdim 51343171Sdim MDBuilder MDB(Guard->getContext()); 52343171Sdim CheckBI->setMetadata(LLVMContext::MD_prof, 53343171Sdim MDB.createBranchWeights(PredicatePassBranchWeight, 1)); 54343171Sdim 55343171Sdim IRBuilder<> B(DeoptBlockTerm); 56343171Sdim auto *DeoptCall = B.CreateCall(DeoptIntrinsic, Args, {DeoptOB}, ""); 57343171Sdim 58343171Sdim if (DeoptIntrinsic->getReturnType()->isVoidTy()) { 59343171Sdim B.CreateRetVoid(); 60343171Sdim } else { 61343171Sdim DeoptCall->setName("deoptcall"); 62343171Sdim B.CreateRet(DeoptCall); 63343171Sdim } 64343171Sdim 65343171Sdim DeoptCall->setCallingConv(Guard->getCallingConv()); 66343171Sdim DeoptBlockTerm->eraseFromParent(); 67360784Sdim 68360784Sdim if (UseWC) { 69360784Sdim // We want the guard to be expressed as explicit control flow, but still be 70360784Sdim // widenable. For that, we add Widenable Condition intrinsic call to the 71360784Sdim // guard's condition. 72360784Sdim IRBuilder<> B(CheckBI); 73360784Sdim auto *WC = B.CreateIntrinsic(Intrinsic::experimental_widenable_condition, 74360784Sdim {}, {}, nullptr, "widenable_cond"); 75360784Sdim CheckBI->setCondition(B.CreateAnd(CheckBI->getCondition(), WC, 76360784Sdim "exiplicit_guard_cond")); 77360784Sdim assert(isWidenableBranch(CheckBI) && "sanity check"); 78360784Sdim } 79343171Sdim} 80360784Sdim 81360784Sdim 82360784Sdimvoid llvm::widenWidenableBranch(BranchInst *WidenableBR, Value *NewCond) { 83360784Sdim assert(isWidenableBranch(WidenableBR) && "precondition"); 84360784Sdim 85360784Sdim // The tempting trivially option is to produce something like this: 86360784Sdim // br (and oldcond, newcond) where oldcond is assumed to contain a widenable 87360784Sdim // condition, but that doesn't match the pattern parseWidenableBranch expects 88360784Sdim // so we have to be more sophisticated. 89360784Sdim 90360784Sdim Use *C, *WC; 91360784Sdim BasicBlock *IfTrueBB, *IfFalseBB; 92360784Sdim parseWidenableBranch(WidenableBR, C, WC, IfTrueBB, IfFalseBB); 93360784Sdim if (!C) { 94360784Sdim // br (wc()), ... form 95360784Sdim IRBuilder<> B(WidenableBR); 96360784Sdim WidenableBR->setCondition(B.CreateAnd(NewCond, WC->get())); 97360784Sdim } else { 98360784Sdim // br (wc & C), ... form 99360784Sdim IRBuilder<> B(WidenableBR); 100360784Sdim C->set(B.CreateAnd(NewCond, C->get())); 101360784Sdim Instruction *WCAnd = cast<Instruction>(WidenableBR->getCondition()); 102360784Sdim // Condition is only guaranteed to dominate branch 103360784Sdim WCAnd->moveBefore(WidenableBR); 104360784Sdim } 105360784Sdim assert(isWidenableBranch(WidenableBR) && "preserve widenabiliy"); 106360784Sdim} 107360784Sdim 108360784Sdimvoid llvm::setWidenableBranchCond(BranchInst *WidenableBR, Value *NewCond) { 109360784Sdim assert(isWidenableBranch(WidenableBR) && "precondition"); 110360784Sdim 111360784Sdim Use *C, *WC; 112360784Sdim BasicBlock *IfTrueBB, *IfFalseBB; 113360784Sdim parseWidenableBranch(WidenableBR, C, WC, IfTrueBB, IfFalseBB); 114360784Sdim if (!C) { 115360784Sdim // br (wc()), ... form 116360784Sdim IRBuilder<> B(WidenableBR); 117360784Sdim WidenableBR->setCondition(B.CreateAnd(NewCond, WC->get())); 118360784Sdim } else { 119360784Sdim // br (wc & C), ... form 120360784Sdim Instruction *WCAnd = cast<Instruction>(WidenableBR->getCondition()); 121360784Sdim // Condition is only guaranteed to dominate branch 122360784Sdim WCAnd->moveBefore(WidenableBR); 123360784Sdim C->set(NewCond); 124360784Sdim } 125360784Sdim assert(isWidenableBranch(WidenableBR) && "preserve widenabiliy"); 126360784Sdim} 127