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 analyzes related to guards and their 9 // conditions. 10 //===----------------------------------------------------------------------===// 11 12 #include "llvm/Analysis/GuardUtils.h" 13 #include "llvm/IR/PatternMatch.h" 14 15 using namespace llvm; 16 17 bool llvm::isGuard(const User *U) { 18 using namespace llvm::PatternMatch; 19 return match(U, m_Intrinsic<Intrinsic::experimental_guard>()); 20 } 21 22 bool llvm::isWidenableBranch(const User *U) { 23 Value *Condition, *WidenableCondition; 24 BasicBlock *GuardedBB, *DeoptBB; 25 return parseWidenableBranch(U, Condition, WidenableCondition, GuardedBB, 26 DeoptBB); 27 } 28 29 bool llvm::isGuardAsWidenableBranch(const User *U) { 30 Value *Condition, *WidenableCondition; 31 BasicBlock *GuardedBB, *DeoptBB; 32 if (!parseWidenableBranch(U, Condition, WidenableCondition, GuardedBB, 33 DeoptBB)) 34 return false; 35 using namespace llvm::PatternMatch; 36 for (auto &Insn : *DeoptBB) { 37 if (match(&Insn, m_Intrinsic<Intrinsic::experimental_deoptimize>())) 38 return true; 39 if (Insn.mayHaveSideEffects()) 40 return false; 41 } 42 return false; 43 } 44 45 bool llvm::parseWidenableBranch(const User *U, Value *&Condition, 46 Value *&WidenableCondition, 47 BasicBlock *&IfTrueBB, BasicBlock *&IfFalseBB) { 48 using namespace llvm::PatternMatch; 49 if (!match(U, m_Br(m_And(m_Value(Condition), m_Value(WidenableCondition)), 50 IfTrueBB, IfFalseBB))) 51 return false; 52 // For the branch to be (easily) widenable, it must not correlate with other 53 // branches. Thus, the widenable condition must have a single use. 54 if (!WidenableCondition->hasOneUse() || 55 !cast<BranchInst>(U)->getCondition()->hasOneUse()) 56 return false; 57 // TODO: At the moment, we only recognize the branch if the WC call in this 58 // specific position. We should generalize! 59 return match(WidenableCondition, 60 m_Intrinsic<Intrinsic::experimental_widenable_condition>()); 61 } 62