GuardUtils.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  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. #include "llvm/Analysis/GuardUtils.h"
  12. #include "llvm/IR/PatternMatch.h"
  13. using namespace llvm;
  14. using namespace llvm::PatternMatch;
  15. bool llvm::isGuard(const User *U) {
  16. return match(U, m_Intrinsic<Intrinsic::experimental_guard>());
  17. }
  18. bool llvm::isWidenableBranch(const User *U) {
  19. Value *Condition, *WidenableCondition;
  20. BasicBlock *GuardedBB, *DeoptBB;
  21. return parseWidenableBranch(U, Condition, WidenableCondition, GuardedBB,
  22. DeoptBB);
  23. }
  24. bool llvm::isGuardAsWidenableBranch(const User *U) {
  25. Value *Condition, *WidenableCondition;
  26. BasicBlock *GuardedBB, *DeoptBB;
  27. if (!parseWidenableBranch(U, Condition, WidenableCondition, GuardedBB,
  28. DeoptBB))
  29. return false;
  30. for (auto &Insn : *DeoptBB) {
  31. if (match(&Insn, m_Intrinsic<Intrinsic::experimental_deoptimize>()))
  32. return true;
  33. if (Insn.mayHaveSideEffects())
  34. return false;
  35. }
  36. return false;
  37. }
  38. bool llvm::parseWidenableBranch(const User *U, Value *&Condition,
  39. Value *&WidenableCondition,
  40. BasicBlock *&IfTrueBB, BasicBlock *&IfFalseBB) {
  41. Use *C, *WC;
  42. if (parseWidenableBranch(const_cast<User*>(U), C, WC, IfTrueBB, IfFalseBB)) {
  43. if (C)
  44. Condition = C->get();
  45. else
  46. Condition = ConstantInt::getTrue(IfTrueBB->getContext());
  47. WidenableCondition = WC->get();
  48. return true;
  49. }
  50. return false;
  51. }
  52. bool llvm::parseWidenableBranch(User *U, Use *&C,Use *&WC,
  53. BasicBlock *&IfTrueBB, BasicBlock *&IfFalseBB) {
  54. auto *BI = dyn_cast<BranchInst>(U);
  55. if (!BI || !BI->isConditional())
  56. return false;
  57. auto *Cond = BI->getCondition();
  58. if (!Cond->hasOneUse())
  59. return false;
  60. IfTrueBB = BI->getSuccessor(0);
  61. IfFalseBB = BI->getSuccessor(1);
  62. if (match(Cond, m_Intrinsic<Intrinsic::experimental_widenable_condition>())) {
  63. WC = &BI->getOperandUse(0);
  64. C = nullptr;
  65. return true;
  66. }
  67. // Check for two cases:
  68. // 1) br (i1 (and A, WC())), label %IfTrue, label %IfFalse
  69. // 2) br (i1 (and WC(), B)), label %IfTrue, label %IfFalse
  70. // We do not check for more generalized and trees as we should canonicalize
  71. // to the form above in instcombine. (TODO)
  72. Value *A, *B;
  73. if (!match(Cond, m_And(m_Value(A), m_Value(B))))
  74. return false;
  75. auto *And = dyn_cast<Instruction>(Cond);
  76. if (!And)
  77. // Could be a constexpr
  78. return false;
  79. if (match(A, m_Intrinsic<Intrinsic::experimental_widenable_condition>()) &&
  80. A->hasOneUse()) {
  81. WC = &And->getOperandUse(0);
  82. C = &And->getOperandUse(1);
  83. return true;
  84. }
  85. if (match(B, m_Intrinsic<Intrinsic::experimental_widenable_condition>()) &&
  86. B->hasOneUse()) {
  87. WC = &And->getOperandUse(1);
  88. C = &And->getOperandUse(0);
  89. return true;
  90. }
  91. return false;
  92. }