123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- //===-- GuardUtils.cpp - Utils for work with guards -------------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- // Utils that are used to perform analyzes related to guards and their
- // conditions.
- //===----------------------------------------------------------------------===//
- #include "llvm/Analysis/GuardUtils.h"
- #include "llvm/IR/PatternMatch.h"
- using namespace llvm;
- using namespace llvm::PatternMatch;
- bool llvm::isGuard(const User *U) {
- return match(U, m_Intrinsic<Intrinsic::experimental_guard>());
- }
- bool llvm::isWidenableBranch(const User *U) {
- Value *Condition, *WidenableCondition;
- BasicBlock *GuardedBB, *DeoptBB;
- return parseWidenableBranch(U, Condition, WidenableCondition, GuardedBB,
- DeoptBB);
- }
- bool llvm::isGuardAsWidenableBranch(const User *U) {
- Value *Condition, *WidenableCondition;
- BasicBlock *GuardedBB, *DeoptBB;
- if (!parseWidenableBranch(U, Condition, WidenableCondition, GuardedBB,
- DeoptBB))
- return false;
- for (auto &Insn : *DeoptBB) {
- if (match(&Insn, m_Intrinsic<Intrinsic::experimental_deoptimize>()))
- return true;
- if (Insn.mayHaveSideEffects())
- return false;
- }
- return false;
- }
- bool llvm::parseWidenableBranch(const User *U, Value *&Condition,
- Value *&WidenableCondition,
- BasicBlock *&IfTrueBB, BasicBlock *&IfFalseBB) {
- Use *C, *WC;
- if (parseWidenableBranch(const_cast<User*>(U), C, WC, IfTrueBB, IfFalseBB)) {
- if (C)
- Condition = C->get();
- else
- Condition = ConstantInt::getTrue(IfTrueBB->getContext());
- WidenableCondition = WC->get();
- return true;
- }
- return false;
- }
- bool llvm::parseWidenableBranch(User *U, Use *&C,Use *&WC,
- BasicBlock *&IfTrueBB, BasicBlock *&IfFalseBB) {
- auto *BI = dyn_cast<BranchInst>(U);
- if (!BI || !BI->isConditional())
- return false;
- auto *Cond = BI->getCondition();
- if (!Cond->hasOneUse())
- return false;
- IfTrueBB = BI->getSuccessor(0);
- IfFalseBB = BI->getSuccessor(1);
- if (match(Cond, m_Intrinsic<Intrinsic::experimental_widenable_condition>())) {
- WC = &BI->getOperandUse(0);
- C = nullptr;
- return true;
- }
- // Check for two cases:
- // 1) br (i1 (and A, WC())), label %IfTrue, label %IfFalse
- // 2) br (i1 (and WC(), B)), label %IfTrue, label %IfFalse
- // We do not check for more generalized and trees as we should canonicalize
- // to the form above in instcombine. (TODO)
- Value *A, *B;
- if (!match(Cond, m_And(m_Value(A), m_Value(B))))
- return false;
- auto *And = dyn_cast<Instruction>(Cond);
- if (!And)
- // Could be a constexpr
- return false;
- if (match(A, m_Intrinsic<Intrinsic::experimental_widenable_condition>()) &&
- A->hasOneUse()) {
- WC = &And->getOperandUse(0);
- C = &And->getOperandUse(1);
- return true;
- }
- if (match(B, m_Intrinsic<Intrinsic::experimental_widenable_condition>()) &&
- B->hasOneUse()) {
- WC = &And->getOperandUse(1);
- C = &And->getOperandUse(0);
- return true;
- }
- return false;
- }
|