13c284bdeSMax Kazantsev //===-- GuardUtils.cpp - Utils for work with guards -------------*- C++ -*-===//
23c284bdeSMax Kazantsev //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63c284bdeSMax Kazantsev //
73c284bdeSMax Kazantsev //===----------------------------------------------------------------------===//
83c284bdeSMax Kazantsev // Utils that are used to perform analyzes related to guards and their
93c284bdeSMax Kazantsev // conditions.
103c284bdeSMax Kazantsev //===----------------------------------------------------------------------===//
113c284bdeSMax Kazantsev 
123c284bdeSMax Kazantsev #include "llvm/Analysis/GuardUtils.h"
133c284bdeSMax Kazantsev #include "llvm/IR/PatternMatch.h"
143c284bdeSMax Kazantsev 
153c284bdeSMax Kazantsev using namespace llvm;
16aaea2480SPhilip Reames using namespace llvm::PatternMatch;
173c284bdeSMax Kazantsev 
isGuard(const User * U)183c284bdeSMax Kazantsev bool llvm::isGuard(const User *U) {
193c284bdeSMax Kazantsev   return match(U, m_Intrinsic<Intrinsic::experimental_guard>());
203c284bdeSMax Kazantsev }
21bd374b27SMax Kazantsev 
isWidenableBranch(const User * U)2270c68a6bSPhilip Reames bool llvm::isWidenableBranch(const User *U) {
2370c68a6bSPhilip Reames   Value *Condition, *WidenableCondition;
2470c68a6bSPhilip Reames   BasicBlock *GuardedBB, *DeoptBB;
2570c68a6bSPhilip Reames   return parseWidenableBranch(U, Condition, WidenableCondition, GuardedBB,
2670c68a6bSPhilip Reames                               DeoptBB);
2770c68a6bSPhilip Reames }
2870c68a6bSPhilip Reames 
isGuardAsWidenableBranch(const User * U)29bd374b27SMax Kazantsev bool llvm::isGuardAsWidenableBranch(const User *U) {
30ca47f1f7SMax Kazantsev   Value *Condition, *WidenableCondition;
31ca47f1f7SMax Kazantsev   BasicBlock *GuardedBB, *DeoptBB;
32ca47f1f7SMax Kazantsev   if (!parseWidenableBranch(U, Condition, WidenableCondition, GuardedBB,
33ca47f1f7SMax Kazantsev                             DeoptBB))
34ca47f1f7SMax Kazantsev     return false;
35ca47f1f7SMax Kazantsev   for (auto &Insn : *DeoptBB) {
36bd374b27SMax Kazantsev     if (match(&Insn, m_Intrinsic<Intrinsic::experimental_deoptimize>()))
37bd374b27SMax Kazantsev       return true;
38bd374b27SMax Kazantsev     if (Insn.mayHaveSideEffects())
39bd374b27SMax Kazantsev       return false;
40bd374b27SMax Kazantsev   }
41bd374b27SMax Kazantsev   return false;
42bd374b27SMax Kazantsev }
43ca47f1f7SMax Kazantsev 
parseWidenableBranch(const User * U,Value * & Condition,Value * & WidenableCondition,BasicBlock * & IfTrueBB,BasicBlock * & IfFalseBB)44ca47f1f7SMax Kazantsev bool llvm::parseWidenableBranch(const User *U, Value *&Condition,
45ca47f1f7SMax Kazantsev                                 Value *&WidenableCondition,
46ca47f1f7SMax Kazantsev                                 BasicBlock *&IfTrueBB, BasicBlock *&IfFalseBB) {
478293f743SPhilip Reames 
488293f743SPhilip Reames   Use *C, *WC;
498293f743SPhilip Reames   if (parseWidenableBranch(const_cast<User*>(U), C, WC, IfTrueBB, IfFalseBB)) {
508293f743SPhilip Reames     if (C)
518293f743SPhilip Reames       Condition = C->get();
528293f743SPhilip Reames     else
53aaea2480SPhilip Reames       Condition = ConstantInt::getTrue(IfTrueBB->getContext());
548293f743SPhilip Reames     WidenableCondition = WC->get();
558293f743SPhilip Reames     return true;
568293f743SPhilip Reames   }
578293f743SPhilip Reames   return false;
588293f743SPhilip Reames }
598293f743SPhilip Reames 
parseWidenableBranch(User * U,Use * & C,Use * & WC,BasicBlock * & IfTrueBB,BasicBlock * & IfFalseBB)608293f743SPhilip Reames bool llvm::parseWidenableBranch(User *U, Use *&C,Use *&WC,
618293f743SPhilip Reames                                 BasicBlock *&IfTrueBB, BasicBlock *&IfFalseBB) {
628293f743SPhilip Reames 
638293f743SPhilip Reames   auto *BI = dyn_cast<BranchInst>(U);
648293f743SPhilip Reames   if (!BI || !BI->isConditional())
658293f743SPhilip Reames     return false;
668293f743SPhilip Reames   auto *Cond = BI->getCondition();
678293f743SPhilip Reames   if (!Cond->hasOneUse())
688293f743SPhilip Reames     return false;
698293f743SPhilip Reames 
708293f743SPhilip Reames   IfTrueBB = BI->getSuccessor(0);
718293f743SPhilip Reames   IfFalseBB = BI->getSuccessor(1);
728293f743SPhilip Reames 
738293f743SPhilip Reames   if (match(Cond, m_Intrinsic<Intrinsic::experimental_widenable_condition>())) {
748293f743SPhilip Reames     WC = &BI->getOperandUse(0);
758293f743SPhilip Reames     C = nullptr;
76aaea2480SPhilip Reames     return true;
77aaea2480SPhilip Reames   }
78aaea2480SPhilip Reames 
79aaea2480SPhilip Reames   // Check for two cases:
80aaea2480SPhilip Reames   // 1) br (i1 (and A, WC())), label %IfTrue, label %IfFalse
81aaea2480SPhilip Reames   // 2) br (i1 (and WC(), B)), label %IfTrue, label %IfFalse
82aaea2480SPhilip Reames   // We do not check for more generalized and trees as we should canonicalize
83aaea2480SPhilip Reames   // to the form above in instcombine. (TODO)
848293f743SPhilip Reames   Value *A, *B;
858293f743SPhilip Reames   if (!match(Cond, m_And(m_Value(A), m_Value(B))))
86d3d5d76aSPhilip Reames     return false;
87*3f8a2af8SPhilip Reames   auto *And = dyn_cast<Instruction>(Cond);
88*3f8a2af8SPhilip Reames   if (!And)
89*3f8a2af8SPhilip Reames     // Could be a constexpr
90*3f8a2af8SPhilip Reames     return false;
918293f743SPhilip Reames 
928293f743SPhilip Reames   if (match(A, m_Intrinsic<Intrinsic::experimental_widenable_condition>()) &&
938293f743SPhilip Reames       A->hasOneUse()) {
948293f743SPhilip Reames     WC = &And->getOperandUse(0);
958293f743SPhilip Reames     C = &And->getOperandUse(1);
968293f743SPhilip Reames     return true;
97aaea2480SPhilip Reames   }
98aaea2480SPhilip Reames 
998293f743SPhilip Reames   if (match(B, m_Intrinsic<Intrinsic::experimental_widenable_condition>()) &&
1008293f743SPhilip Reames       B->hasOneUse()) {
1018293f743SPhilip Reames     WC = &And->getOperandUse(1);
1028293f743SPhilip Reames     C = &And->getOperandUse(0);
1038293f743SPhilip Reames     return true;
1048293f743SPhilip Reames   }
1058293f743SPhilip Reames   return false;
106ca47f1f7SMax Kazantsev }
107